window.App = Ember.Application.create({
LOG_TRANSITIONS: true // log routing
});
underscore/underscore.string/lodash
юрл - с него все начинается, route устанавливает модель, которая доступна в контроллере, контроллер определяет переменные в шаблоне, шаблон отображает информацию, outlet используется для показа. Также роут настраивает контроллер и то что будет отрендерено.
контроллеры используются для декорирования моделей.
<script type="text/x-handlebars" data-template-name="my-template"></script>
Use Ember.Object
as a base class, and this._super
to call superclass methods.
App.Person = Ember.Object.extend({
say: function(thing) {
var name = this.get('name');
alert(name + " says: " + thing);
}
});
App.Soldier = App.Person.extend({
say: function(thing) {
this._super(thing + ", sir!");
}
});
var yehuda = App.Soldier.create({
name: "Yehuda Katz"
});
yehuda.say("Yes");
// alerts "Yehuda Katz says: Yes, sir!"
Use .create({options})
to create new instance. Also define init
as a constructor.
var Person = Ember.Object.extend({
init: function() {
var name = this.get('name');
alert(name + ", reporting for duty!");
}
});
Person.create({
name: "Stefan Penner"
});
// alerts "Stefan Penner, reporting for duty!"
When accessing the properties of an object, use the get and set accessor methods
var person = App.Person.create();
var name = person.get('name');
person.set('name', "Tobias Fünke");
App.Person = Ember.Object.extend({
firstName: null,
lastName: null,
age: null,
country: null,
fullName: function() {
return this.get('firstName') + ' ' + this.get('lastName');
}.property('firstName', 'lastName'),
description: function() {
return this.get('fullName') + '; Age: ' + this.get('age') + '; Country: ' + this.get('country');
}.property('fullName', 'age', 'country')
});
var captainAmerica = App.Person.create({
firstName: 'Steve',
lastName: 'Rogers',
age: 80,
country: 'USA'
});
captainAmerica.get('description'); // "Steve Rogers; Age: 80; Country: USA"
Computed properties, by default, observe any changes made to the properties they depend on and are dynamically updated when they’re called.
With one function we can define getter and setter.
App.Person = Ember.Object.extend({
firstName: null,
lastName: null,
fullName: function(key, value) {
// setter
if (arguments.length > 1) {
var nameParts = value.split(/\s+/);
this.set('firstName', nameParts[0]);
this.set('lastName', nameParts[1]);
}
// getter
return this.get('firstName') + ' ' + this.get('lastName');
}.property('firstName', 'lastName')
});
var captainAmerica = App.Person.create();
captainAmerica.set('fullName', "William Burnside");
captainAmerica.get('firstName'); // William
captainAmerica.get('lastName'); // Burnside
App.TodosController = Ember.Controller.extend({
todos: [
Ember.Object.create({ isDone: false })
],
remaining: function() {
var todos = this.get('todos');
return todos.filterBy('isDone', false).get('length');
}.property('todos.@each.isDone')
});
var todos = App.todosController.get('todos');
App.todosController.get('remaining');
// 1
var todo = todos.objectAt(0);
todo.set('isDone', true);
App.todosController.get('remaining');
// 0
todo = Ember.Object.create({ isDone: false });
todos.pushObject(todo);
App.todosController.get('remaining');
// 1
Person.reopen({
fullNameChanged: Ember.observer('fullName', function() {
// deal with the change
})
});
Person.reopen({
partOfNameChanged: function() {
Ember.run.once(this, 'processFullName');
}.observes('firstName', 'lastName'),
processFullName: function() {
// This will only fire once if you set two properties at the same time, and
// will also happen in the next run loop once all properties are synchronized
console.log(this.get('fullName'));
}
});
person.set('firstName', 'John');
person.set('lastName', 'Smith');
App.wife = Ember.Object.create({
householdIncome: 80000
});
App.husband = Ember.Object.create({
householdIncomeBinding: 'App.wife.householdIncome'
});
App.husband.get('householdIncome'); // 80000
// Someone gets raise.
App.husband.set('householdIncome', 90000);
App.wife.get('householdIncome'); // 90000
application
<header>
<h1>Igor's Blog</h1>
</header>
<div>
{{outlet}}
</div>
<footer>
©2013 Igor's Publishing, Inc.
</footer>
data-template-name
attribute to setup nameExample:
Hello, <strong>{{firstName}} {{lastName}}</strong>!
App.ApplicationController = Ember.Controller.extend({
firstName: "Trek",
lastName: "Glowacki"
});
result:
Hello, <strong>Trek Glowacki</strong>!
Use name, instead of changing context
{{name}}'s Friends
<ul>
{{#each friend in friends}}
<li>{{name}}'s friend {{friend.name}}</li>
{{/each}}
</ul>
Use else
for empty sets
{{#each people}}
Hello, {{name}}!
{{else}}
Sorry, nobody is here.
{{/each}}
To bind attribute to some of controller properties. For false
values attr ignores.
<input type="checkbox" {{bind-attr disabled=isAdministrator}}>
<img {{bind-attr src=logoUrl}} alt="Logo">
Regular values:
<div {{bind-attr class="isUrgent priority"}}>
Warning!
</div>
Bind boolean values:
Static (regular html) classes:
<div {{bind-attr class=":high-priority isUrgent"}}>
Warning!
</div>
Generates dynamic links:
App.Router.map(function() {
this.resource("photos", function(){
this.route("edit", { path: "/:photo_id" });
});
});
<ul>
{{#each photo in photos}}
<li>{{#link-to 'photos.edit' photo}}{{photo.title}}{{/link-to}}</li>
{{/each}}
</ul>
<ul>
<li><a href="/photos/1">Happy Kittens</a></li>
<li><a href="/photos/2">Puppy Running</a></li>
<li><a href="/photos/3">Mountain Landscape</a></li>
</ul>
It also supports nested resources.
{{#link-to 'photo.comment' nextPhoto primaryComment}}
{{action "select" post}}
on="mouseUp"
bubbles=false
to disable itallowedKeys="alt"
target="view"
Reacts on updates from model.
Ember.Handlebars.helper('fullName', function(person) {
return person.get('firstName') + ' ' + person.get('lastName');
}, 'firstName', 'lastName');
Custom view helper:
Ember.Handlebars.helper(‘calendar’, App.CalendarView) -> {{view App.CalendarView}}