building modern javascript applications with ember.js
Sam Selikoff
Boston, MA
•
September 11, 2014
`whoami`
Front-end engineer
@ samselikoff
WEB APPS
js, a brief history
server-side
server-side rendering
GET wikipedia.org/napolean -->
GET wikipedia.org/France -->
Route request, fetch data
<-- HTML/CSS
Views, click form/link
Problems
- Only links and forms respond to user input
- Limited behavior
Need our UIs to be
more dynamic
sprinkle some javascript
"Can we make that form AJAX?"
"Let's add infinite scrolling"
"Dynamic dropdowns"
"Why don't we prefetch that data"
sprinkle some js
GET github.com -->
Route request, fetch data
<-- HTML/CSS
<-- JS
Views, click form/link, interacts with JS
AJAX/non-AJAX request -->
<-- JSON/HTML
The libraries cometh
PROBLEMS
- Maintainability
- No shared solutions
- Hard to detect architectural flaws
Need a complete plan
for our JavaScript
javascript apps
Frameworks help us avoid the
architecture problems of the past
JS Apps
GET gmail.com -->
Fetch JS app, initial data
<-- HTML/CSS
<-- JS app, templates
Loads app, interacts with JS
AJAX request -->
<-- JSON
JS now controls
- routing
- templates + rendering
- data syncing
- responding to user input
- authentication
- persistence
- ...
A framework for building ambitious web applications
what is a framework?
helps you out
promotes
sharing
embraces conventions
what are ambitious web apps?
native-like
url driven
overview
of Ember
router
-
URLs
-
UI hierarchy
URLs
-
/inbox
-
/message/1234
-
/contacts
Router.map(function() {
this.route('inbox');
this.resource('message', {path: '/:message_id'});
this.resource('contacts');
});
route
- one per URL
- retrieve related model via AJAX
export default Ember.Route.extend({
model: function() {
return Ember.getJSON('/contacts');
}
});
templates
- Handlebars
- Render your model(s) in HTML
- Data binding
<h1>{{title}}</h1>
{{#each contact in contacts}}
<div class='contact-card'>
<h2>{{contact.name}}</h2>
<h3>{{contact.email}}</h3>
</div>
{{/each}}
controllers
- Hold application state
- Presenters
- Great place for computed properties
// controllers/contact.js
export default Ember.ObjectController.extend({
fullName: function() {
return this.get('firstName') + ' ' + this.get('lastName');
}.property('firstName', 'lastname')
});
// templates/contacts.hbs
{{#each contact in contacts}}
<p>{{contact.fullName}}</p>
{{/each}}
views
- Render templates
- Great place for manual DOM manipulation
// views/profile-card.js
export default Ember.View.extend({
didInsertElement: function() {
this.$().somePlugin();
}
});
// templates/contacts.hbs
{{#each contact in contacts}}
{{view 'profile-card'}}
{{/each}}
components
- Subclass of View
- Act as their own Controller
<div class="sidebar">
<label >Select a date</label>
{{date-picker selectedDate=currentMonth mode='month'}}
</div>
actions
- Add user interaction
-
DOM events => semantic events
- Bubbling
// templates/index.hbs
<div>
<a id='delete-contact' {{action 'deleteContact' this}}>Delete</a>
</div>
// a-view.js, a-component.js, a-controller.js, a-route.js
actions: {
deleteContact: function(contact) {
contact.delete();
}
}
models
-
Ember Data
- v1.0.0-beta.9
-
Can always use Ember.Object
// models/contact.js
export default DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
age: DS.attr('number'),
addresses: DS.hasMany('address')
});
// some-route.js
model: function() {
return this.store.find('contact');
}
demo
ember-cli
thanks!
github.com/samselikoff/talks
slides.com/samselikoff/intro-to-emberjs
@samselikoff
Building Modern JS Apps with EmberJS
By Sam Selikoff
Building Modern JS Apps with EmberJS
- 3,822