You'll see up here some fortune 500 and some other recognizable company names that are using Ember. Qualcomm just recently relaunched their entire public facing website along with the help of digital agency Digitaria.
App grows, complexity doesn't Sam Mueller, Yahoo Ad-Manager Plus
Ember has the ability to manage the complexity of large applications and websites with grace Jackie Hade, from Digitaria on Qualcomm
The fact that Ember is so opinionated... any Ember developer can look at any other Ember application and immediately have a huge benefit Lance Harper, NBCNews
When tasked with building a robust, powerful, and ambitious web applicaiton, Ember is the tool for that job. These are some quotes from some of the companies I showed before on why they chose ember. You'll see some common themes when reading these quotes or information online about why individuals or companies choose EmberWhere did we come from?
Ember didn't come out of nowhere boasting some serious muscle. There has been a long line of front-end web technologies that have led up to the modern day client-side solutions, like Ember. It has improved on the solutions built before it, and exceeded them.Ajax
DOM Selection and Traversing
Events, Effects, and Animations
Extensible
I was working a web dev position when jQuery came up on my radar. The ease of making ajax calls was enough for me to incorperate it immediately. The dom selection engine made manipulating the dom much easier and more shorthand, with chaining and traversing. Never been a fan of jquery plugins as they far too often incur performance problems, but jquery also bosted being 'highly extensible' Soon the entire application had nearly been rewritten with much more of the logic being moved to the client from the server. Just as fast, this code became difficult to manage, or even find scattered throughout the proejct, as was the case with many a jquery project.Lean MVC
Small Footprint
Easy to Learn
Provides Basic Tools
The next big leap was Backbone and it improved the quality of life for many front-end developers. jquery or other selector engine dependency It offered a lean approach to MVC with a minimal learning curve, only a few core concepts to master. A lot of boilerplate that had to be handled by the developer. No structure. Memory management is a serious consideration for backbone developers, view lifecycle must be well managed or memory leaks are all too easy. Provides basic toolset for building an application or custom framework. Is not a framework.Two-Way Binding
Manages View Life-Cycle
Automatic Creation
Router
Ember-Data
Performance
Two-Way binding in today's generation of client-side tech has really simplified templates and leaned down a lot of logic that had to be done prior to update views. Setup and teardown of views Automatically create Routes, Controllers and Views even if you haven't defined them yourself. Ember-Data is an optional model layer that provides a way to interact with data on your server, cache them for performance and can be used without much configuration for most projects Because Ember is so particular, it makes good app management decisions so you don't have to. Optimizes updates to the DOM when data change, Caching of computed properties, only recalculates when necessary.app/templates/application.hbs
<header> {{#link-to 'index'}} <i class="fa fa-circle fa-emgur-logo"></i> Emgur {{/link-to}} </header> <div class="main-container"> {{outlet}} </div>Here is what our application template file looks like. Any time the route changes, the template will be rendered inside the outlet tag.
app/routes/index.js
import Ember from 'ember'; export default Ember.Route.extend({ model: function() { return this.store.find('gallery'); } });this.store gives access to the data store. model is a special hook on the route that provides the main content to the controller. this.store.find returns a promise and Ember will wait for that promise to resolve before rendering the template.
app/templates/index.hbs
<div class="container"> {{#each}} {{image-thumb content=this}} {{/each}} <div class="clear"></div> </div>each default behavior is to loop over the content provided in the route. image-thumb is a component that will display the thumbnail, manage the hover state, and show the comments count.
:isHovering
commentCount
here is a demo of how the interaction is going to work. basically we want the gradient and comment count to show up when we hover, along with the border. The border we do with css, simple :hover selector. The content for the count we'll use a flag on the component. Also, the comments for a given gallery item will have to be totalled. This isn't on the data model so this will have to be an attribute on the component.app/components/image-thumb.js
import Ember from 'ember'; export default Ember.Component.extend({ isHovering: false, commentsCount: function() { return this.get('content.comments.length'); }.property('content.comments'), mouseEnter: function() { this.set('isHovering', true); }, mouseLeave: function() { this.set('isHovering', false); } });pretty simple component but it gives you an idea of a component. `content` is passed in and we get the comment count by grabbing the length of the comments array. the isHovering toggles when the mouseOver and mouseLeave events fire. components, like views, are evented and implement touch, drag/drop, mouse, key and form events. Custom events can also be registered.
app/templates/components/image-thumb.hbs
{{#link-to 'gallery' content}} <div class="image-item"> <div class="image-thumb"> <img {{bind-attr src=content.image.url}}> </div> {{#if isHovering}} <div class="image-details"> <div class="image-comment"> <div class="comment-count">{{commentsCount}} comments</div> </div> </div> {{/if}} </div> {{/link-to}}here we can see the isHovering flag at work in the handlebars template. we can also see the `bind-attr` handlebars helper. this comes in handy with images, or other attributes you may want to bind like height, width, or even data-attrbutes you may be using for interactions with other libraries.
app/router.js
import Ember from 'ember'; import config from './config/environment'; var Router = Ember.Router.extend({ location: config.locationType }); Router.map(function() { this.route('gallery', { path: '/gallery/:gallery_id' }); }); export default Router;We don't need to define the main index or app route, ember will do that for us as we saw before. If we name the parameters with the model name and follow it with the `_id` we won't need to write these routes. The default behavior for the route will be to look up the model, in this case `gallery` and do a find with the passed in id number.
app/templates/gallery.hbs
<div class="gallery-container"> <div class="gallery-full"> <div class="gallery-title">{{title}}</div> <div class="gallery-posted">{{postedFormated}}</div> <div class="gallery-image"> <img {{bind-attr src=image.url}}> </div> </div> <div class="gallery-comments"> <div class="comment-new"> {{#if isEditing}} {{focus-textarea value=newComment rows=3 focus-out='offEdit' action='submitComment'}} <div class="comment-button-container"> <div class='save-button' {{action 'submitComment'}}>save</div> <div class="comment-length">{{newCommentCharacters}}</div> </div> <div class="clear"></div> {{else}} {{input placeholder='Submit a comment' focus-in='onEdit'}} {{/if}} </div> <ul class="gallery-comments-ul"> {{#each comments}} <li class="gallery-comment"> <div class="comment-posted">{{postedFormatted}}</div> <div class="comment-content">{{content}}</div> </li> {{/each}} </ul></div> </div> <!-- TODO --> <div class="gallery-navigation"></div>This template has a bit more going on since there is more interaction available between the user and the application. I'm going to step through the unfamiliar pieces.
app/templates/gallery.hbs
bind-attr is a handlebars helper that allows for ember objects to be bound to a dom element attribute. in this example, the src for an image.app/templates/gallery.hbs
focus-textarea is another component that extends the default ember textarea. this component has quite a few more attributes than the one prior and even has some actions being defined.app/templates/gallery.hbs
action is another handlebars helper that triggers an event. these actions bubble up until the action is found.app/templates/gallery.hbs
loop over each commentapp/controllers/gallery.js
import Ember from 'ember'; export default Ember.ObjectController.extend({ maxChars: 140, isEditing: false, newComment: null, // bound to value of textarea postedFormated: function() { return moment(this.get('posted')).fromNow(); }.property('posted'), newCommentCharacters: function() { return this.maxChars - this.get('newComment.length'); }.property('newComment'), actions: { onEdit: function() { this.set('isEditing', true); }, offEdit: function() { if (this.get('newCommentCharacters') === this.maxChars) { this.set('isEditing', false); } }, submitComment: function() { var _this = this; var comment = this.store.createRecord('comment', { content: this.get('newComment') }); comment.save().then(function(comment) { var gallery = _this.get('content'); gallery.get('comments').pushObject(comment); gallery.save().then(function(gallery) { _this.setProperties({ newComment: null, isEditing: false }); }); }); } } });
#emberjs