Introduzione a Ember.js

Post on 15-Apr-2017

579 views 0 download

transcript

Testo

Introduzione a Ember.js“A framework for creating ambitious web applications”

AgendaEmber e ember-cli Template Routing Modelli e Ember-Data Controller Componenti Addons Risorse

Ember.js“The web derives its power from the ability to bookmark and share URLs”

Ember.js

Da creatori/sviluppatori di jQuery, Rails, SproutCore

“The web derives its power from the ability to bookmark and share URLs”

Ember.js

Da creatori/sviluppatori di jQuery, Rails, SproutCore

Moderno framework JS (v.1.0-beta - agosto 2012)

“The web derives its power from the ability to bookmark and share URLs”

Ember.js

Da creatori/sviluppatori di jQuery, Rails, SproutCore

Moderno framework JS (v.1.0-beta - agosto 2012)

Finora piuttosto instabile, ma v.2.0 il 24/07/15

“The web derives its power from the ability to bookmark and share URLs”

Ember.js

Da creatori/sviluppatori di jQuery, Rails, SproutCore

Moderno framework JS (v.1.0-beta - agosto 2012)

Finora piuttosto instabile, ma v.2.0 il 24/07/15

Opinionated framework: convention-over-configuration

“The web derives its power from the ability to bookmark and share URLs”

Ember.js

Da creatori/sviluppatori di jQuery, Rails, SproutCore

Moderno framework JS (v.1.0-beta - agosto 2012)

Finora piuttosto instabile, ma v.2.0 il 24/07/15

Opinionated framework: convention-over-configuration

Largo uso di ECMAScript 6 (o simili, come RSVP)

“The web derives its power from the ability to bookmark and share URLs”

Ciclo di sviluppo

Release Beta Canary1.13.0 2.0.0-beta1 2.0.0-canary+680f997e

Ember-cli

Ember-cliCommand-line-interface per gestire un progetto Ember

Ember-cliCommand-line-interface per gestire un progetto Ember

Asset pipeline con Broccoli (supporto per Handlebars, CoffeeScript, Sass, Less, minifier, uglifier, ecc.)

Ember-cliCommand-line-interface per gestire un progetto Ember

Asset pipeline con Broccoli (supporto per Handlebars, CoffeeScript, Sass, Less, minifier, uglifier, ecc.)

Rigida struttura convenzionale di file/cartelle (occhio ai nomi!)

Ember-cliCommand-line-interface per gestire un progetto Ember

Asset pipeline con Broccoli (supporto per Handlebars, CoffeeScript, Sass, Less, minifier, uglifier, ecc.)

Rigida struttura convenzionale di file/cartelle (occhio ai nomi!)

Compilazione al volo ad ogni file salvato in sviluppo

Ember-cliCommand-line-interface per gestire un progetto Ember

Asset pipeline con Broccoli (supporto per Handlebars, CoffeeScript, Sass, Less, minifier, uglifier, ecc.)

Rigida struttura convenzionale di file/cartelle (occhio ai nomi!)

Compilazione al volo ad ogni file salvato in sviluppo

Generatori di risorse, server di sviluppo, installazione addon

Ember-cliCommand-line-interface per gestire un progetto Ember

Asset pipeline con Broccoli (supporto per Handlebars, CoffeeScript, Sass, Less, minifier, uglifier, ecc.)

Rigida struttura convenzionale di file/cartelle (occhio ai nomi!)

Compilazione al volo ad ogni file salvato in sviluppo

Generatori di risorse, server di sviluppo, installazione addon

Test con PhantomJS

Ember-cli - up & runningnpm install -g ember-cli bower phantomjsember new my-new-appcd my-new-appnpm install && bower installember server

Ember-cli - struttura fileapp/ — adapters/ — components/ — controllers/ — helpers/ — models/ — routes/ — styles/ — templates/ — app.js — index.html — router.jsconfig/environment.jsbower.jsonember-cli-build.jspackage.json

Ember-cli - struttura fileapp/ — adapters/ — components/ — controllers/ — helpers/ — models/ — routes/ — styles/ — templates/ — app.js — index.html — router.jsconfig/environment.jsbower.jsonember-cli-build.jspackage.json

Configurazioni dell’applicazione

Ember-cli - struttura fileapp/ — adapters/ — components/ — controllers/ — helpers/ — models/ — routes/ — styles/ — templates/ — app.js — index.html — router.jsconfig/environment.jsbower.jsonember-cli-build.jspackage.json

Gestione delle dipendenze del frontend (bower)

Ember-cli - struttura fileapp/ — adapters/ — components/ — controllers/ — helpers/ — models/ — routes/ — styles/ — templates/ — app.js — index.html — router.jsconfig/environment.jsbower.jsonember-cli-build.jspackage.json

Gestione delle dipendenze del

backend (Node.js)

Ember-cli - struttura fileapp/ — adapters/ — components/ — controllers/ — helpers/ — models/ — routes/ — styles/ — templates/ — app.js — index.html — router.jsconfig/environment.jsbower.jsonember-cli-build.jspackage.json

Specifiche della compilazione di Broccoli (librerie, pacchetti, ecc.)

Ember-cli - struttura fileapp/ — adapters/ — components/ — controllers/ — helpers/ — models/ — routes/ — styles/ — templates/ — app.js — index.html — router.jsconfig/environment.jsbower.jsonember-cli-build.jspackage.json

Ember 1.x: MVC Model: gestione dati (prob. ember-data) View (templates): presentazione dati (handlebars) Controller: manipolazione dati per il template

Ember-cli - struttura fileapp/ — adapters/ — components/ — controllers/ — helpers/ — models/ — routes/ — styles/ — templates/ — app.js — index.html — router.jsconfig/environment.jsbower.jsonember-cli-build.jspackage.json

Ember 2.x: full-stack web

framework Model: gestione dati (prob. ember-data) Components: componenti riusabili Templates: presentazione dati (HTMLbars) Router: recupero dati, gestione delle azioni dei template, salvataggio, redirect, ecc. (store, ember-data)

Ember-cli - struttura fileapp/ — adapters/ — components/ — controllers/ — helpers/ — models/ — routes/ — styles/ — templates/ — app.js — index.html — router.jsconfig/environment.jsbower.jsonember-cli-build.jspackage.json

Specifiche delle rotte definisce gli URL (in Ember gli URL

devono essere consistenti)

Ember-cli - struttura fileapp/ — adapters/ — components/ — controllers/ — helpers/ — models/ — routes/ — styles/ — templates/ — app.js — index.html — router.jsconfig/environment.jsbower.jsonember-cli-build.jspackage.json

Componenti elementi riusabili

nell’applicazione, composti da logica+template

Ember-cli - struttura fileapp/ — adapters/ — components/ — controllers/ — helpers/ — models/ — routes/ — styles/ — templates/ — app.js — index.html — router.jsconfig/environment.jsbower.jsonember-cli-build.jspackage.json

Adapters logica di gestione delle API (come

passare i dati, dove ottenerli, ecc.)

Ember-cli - struttura fileapp/ — adapters/ — components/ — controllers/ — helpers/ — models/ — routes/ — styles/ — templates/ — app.js — index.html — router.jsconfig/environment.jsbower.jsonember-cli-build.jspackage.json

Helpers funzioni riusabili (es. parsing di

date con Moment.js)

Ember-cli - generatori

ember generate <generator-name> <options>

Ember-cli - generatori

ember generate <generator-name> <options>

Con l’opzione --pod si possono mantenere tutti i file relativi ad una risorsa nella stessa cartella:

• app/users/controller.js• app/users/route.js• app/users/template.hbs

Ember-cli - generatoriember help generate

Ember-cli - generatori

Available blueprints: liquid-fire: transition <name> Generates a liquid fire transition. ember-select-2: ember-select-2 <name> ember-moment: ember-moment <name> ember-addon: ember-data <name> ember-cli-simple-auth-devise: ember-cli-simple-auth-devise <name> ember-cli-simple-auth: authenticator <name> Generates an Ember Simple Auth authenticator. authorizer <name> Generates an Ember Simple Auth Authorizer. ember-cli-simple-auth <name> session <name> Generates an Ember Simple Auth Session. session-store <name> Generates an Ember Simple Auth Session Store. ember-cli-qunit: ember-cli-qunit <name> ember-cli-divshot: divshot <name> ember-cli-bootstrap-datepicker: bootstrap-datepicker <name> ember-cli: acceptance-test <name> Generates an acceptance test for a feature. adapter <name> <options...> Generates an ember-data adapter. --base-class adapter-test <name> Generates an ember-data adapter unit test addon <name> The default blueprint for ember-cli addons. addon-import <name> Generates an import wrapper.

app <name> The default blueprint for ember-cli projects. blueprint <name> Generates a blueprint and definition. component <name> <options...> Generates a component. Name must contain a hyphen. --path (Default: components) aliases: -no-path (--path=) component-addon <name> Generates a component. Name must contain a hyphen. component-test <name> Generates a component unit test. controller <name> Generates a controller. controller-test <name> Generates a controller unit test. helper <name> Generates a helper function. helper-addon <name> Generates an import wrapper. helper-test <name> Generates a helper unit test. http-mock <endpoint-path> Generates a mock api endpoint in /api prefix. http-proxy <local-path> <remote-url> Generates a relative proxy to another server. in-repo-addon <name> The blueprint for addon in repo ember-cli addons. initializer <name> Generates an initializer. initializer-addon <name> Generates an import wrapper. initializer-test <name> Generates an initializer unit test. lib <name> Generates a lib directory for in-repo addons. mixin <name> Generates a mixin. mixin-test <name> Generates a mixin unit test.

model <name> <attr:type> Generates an ember-data model. model-test <name> Generates a model unit test. resource <name> Generates a model and route. route <name> <options...> Generates a route and registers it with the router. --path (Default: ) route-addon <name> Generates import wrappers for a route and its template. route-test <name> Generates a route unit test. serializer <name> Generates an ember-data serializer. serializer-test <name> Generates a serializer unit test. server <name> Generates a server directory for mocks and proxies. service <name> Generates a service. service-test <name> Generates a service unit test. template <name> Generates a template. test-helper <name> Generates a test helper. transform <name> Generates an ember-data value transform. transform-test <name> Generates a transform unit test. util <name> Generates a simple utility module/function. util-test <name> Generates a util unit test. view <name> Generates a view subclass. view-test <name>

ember help generate

Ember-cli - generatori

Available blueprints: liquid-fire: transition <name> Generates a liquid fire transition. ember-select-2: ember-select-2 <name> ember-moment: ember-moment <name> ember-addon: ember-data <name> ember-cli-simple-auth-devise: ember-cli-simple-auth-devise <name> ember-cli-simple-auth: authenticator <name> Generates an Ember Simple Auth authenticator. authorizer <name> Generates an Ember Simple Auth Authorizer. ember-cli-simple-auth <name> session <name> Generates an Ember Simple Auth Session. session-store <name> Generates an Ember Simple Auth Session Store. ember-cli-qunit: ember-cli-qunit <name> ember-cli-divshot: divshot <name> ember-cli-bootstrap-datepicker: bootstrap-datepicker <name> ember-cli: acceptance-test <name> Generates an acceptance test for a feature. adapter <name> <options...> Generates an ember-data adapter. --base-class adapter-test <name> Generates an ember-data adapter unit test addon <name> The default blueprint for ember-cli addons. addon-import <name> Generates an import wrapper.

app <name> The default blueprint for ember-cli projects. blueprint <name> Generates a blueprint and definition. component <name> <options...> Generates a component. Name must contain a hyphen. --path (Default: components) aliases: -no-path (--path=) component-addon <name> Generates a component. Name must contain a hyphen. component-test <name> Generates a component unit test. controller <name> Generates a controller. controller-test <name> Generates a controller unit test. helper <name> Generates a helper function. helper-addon <name> Generates an import wrapper. helper-test <name> Generates a helper unit test. http-mock <endpoint-path> Generates a mock api endpoint in /api prefix. http-proxy <local-path> <remote-url> Generates a relative proxy to another server. in-repo-addon <name> The blueprint for addon in repo ember-cli addons. initializer <name> Generates an initializer. initializer-addon <name> Generates an import wrapper. initializer-test <name> Generates an initializer unit test. lib <name> Generates a lib directory for in-repo addons. mixin <name> Generates a mixin. mixin-test <name> Generates a mixin unit test.

model <name> <attr:type> Generates an ember-data model. model-test <name> Generates a model unit test. resource <name> Generates a model and route. route <name> <options...> Generates a route and registers it with the router. --path (Default: ) route-addon <name> Generates import wrappers for a route and its template. route-test <name> Generates a route unit test. serializer <name> Generates an ember-data serializer. serializer-test <name> Generates a serializer unit test. server <name> Generates a server directory for mocks and proxies. service <name> Generates a service. service-test <name> Generates a service unit test. template <name> Generates a template. test-helper <name> Generates a test helper. transform <name> Generates an ember-data value transform. transform-test <name> Generates a transform unit test. util <name> Generates a simple utility module/function. util-test <name> Generates a util unit test. view <name> Generates a view subclass. view-test <name>

Anche gli addon possono aggiungere generatori

ember help generate

index.html 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <title>MyNewApp</title> 7 <meta name="description" content=""> 8 <meta name="viewport" content="width=device-width, initial-scale=1"> 9 10 {{content-for 'head'}} 11 12 <link rel="stylesheet" href="assets/vendor.css"> 13 <link rel="stylesheet" href="assets/my-new-app.css"> 14 15 {{content-for 'head-footer'}} 16 </head> 17 <body> 18 {{content-for 'body'}} 19 20 <script src="assets/vendor.js"></script> 21 <script src="assets/my-new-app.js"></script> 22 23 {{content-for 'body-footer'}} 24 </body> 25 </html>

index.html 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <title>MyNewApp</title> 7 <meta name="description" content=""> 8 <meta name="viewport" content="width=device-width, initial-scale=1"> 9 10 {{content-for 'head'}} 11 12 <link rel="stylesheet" href="assets/vendor.css"> 13 <link rel="stylesheet" href="assets/my-new-app.css"> 14 15 {{content-for 'head-footer'}} 16 </head> 17 <body> 18 {{content-for 'body'}} 19 20 <script src="assets/vendor.js"></script> 21 <script src="assets/my-new-app.js"></script> 22 23 {{content-for 'body-footer'}} 24 </body> 25 </html>

vendor.css e vendor.js contengono

css e js delle librerie esterne

index.html 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <title>MyNewApp</title> 7 <meta name="description" content=""> 8 <meta name="viewport" content="width=device-width, initial-scale=1"> 9 10 {{content-for 'head'}} 11 12 <link rel="stylesheet" href="assets/vendor.css"> 13 <link rel="stylesheet" href="assets/my-new-app.css"> 14 15 {{content-for 'head-footer'}} 16 </head> 17 <body> 18 {{content-for 'body'}} 19 20 <script src="assets/vendor.js"></script> 21 <script src="assets/my-new-app.js"></script> 22 23 {{content-for 'body-footer'}} 24 </body> 25 </html>

index.html 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <title>MyNewApp</title> 7 <meta name="description" content=""> 8 <meta name="viewport" content="width=device-width, initial-scale=1"> 9 10 {{content-for 'head'}} 11 12 <link rel="stylesheet" href="assets/vendor.css"> 13 <link rel="stylesheet" href="assets/my-new-app.css"> 14 15 {{content-for 'head-footer'}} 16 </head> 17 <body> 18 {{content-for 'body'}} 19 20 <script src="assets/vendor.js"></script> 21 <script src="assets/my-new-app.js"></script> 22 23 {{content-for 'body-footer'}} 24 </body> 25 </html>

my-new-app.css e my-new-app.js

contengono css e js dell’app

application.hbs 1 <h2 id="title">Welcome to Ember.js</h2> 2 3 {{outlet}}

application.hbs 1 <h2 id="title">Welcome to Ember.js</h2> 2 3 {{outlet}}

{{outlet}} definisce dove i

template “figli” devono inserire il loro

contenuto

application.hbs 1 <h2 id="title">Welcome to Ember.js</h2> 2 3 {{outlet}}

{{outlet}} definisce dove i

template “figli” devono inserire il loro

contenuto

Tutti i template derivano da application.hbs

Template - HTMLBars 1 {{#if users}} 2 {{#each users as |user|}} 3 <p class="user {{if user.isActive 'active' 'inactive'}}"> 4 User: {{#link-to 'users.profile' user}}{{user.name}}{{/link-to}} 5 <button {{action "like" user}}>Like</button> 6 </p> 7 {{/each}} 8 {{else}} 9 Nobody's here.. 10 {{/if}}

È una variante di HandleBars che genera DOM invece di stringhe, con notevole incremento di

prestazioni (+30%)

Routing

1 import Ember from 'ember'; 2 import config from './config/environment'; 3 4 var Router = Ember.Router.extend({ 5 location: config.locationType 6 }); 7 8 Router.map(function() { 9 this.route('people', function() { 10 this.route('new'); 11 this.route('edit', {path: '/:id/edit'}); 12 this.route('contracts', { path: '/:person_id/contracts' }); 13 }); 14 });

Ember.js si fonda sull’URL Il file router.js definisce le rotte e la mappatura degli url:

Routing 1 Router.map(function() { 2 this.route('people', function() {}); 3 });

error e loading sono due rotte usate automaticamente quando il modello è in fase di caricamento o è in errore

Routing

1 import Ember from 'ember'; 2 3 export default Ember.Route.extend({ 4 5 model: function(params) { 6 return this.store.find('myModel', params); 7 }, 8 9 setupController: function(controller, model) { 10 controller.set('model', model); 11 } 12 });

Implementazione di base di una rotta:

Quindi nel controller e nel template è disponibile il modello

Modello associatoOgni rotta ha un modello associato

Modello associatoOgni rotta ha un modello associato

Il modello può essere un POJO, il risultato di una chiamata AJAX con jQuery oppure ottenuto con

Ember-data e lo store

Modello associatoOgni rotta ha un modello associato

Il modello può essere un POJO, il risultato di una chiamata AJAX con jQuery oppure ottenuto con

Ember-data e lo store

1 import Ember from 'ember'; 2 3 export default Ember.Route.extend({ 4 5 model: function() { 6 return this.store.find('myModel'); 7 } 8 });

1 import Ember from 'ember'; 2 3 export default Ember.Route.extend({ 4 5 model: function() { 6 return Ember.$.getJSON(/*…*/) 7 } 8 });

StoreLo store astrae il backend

Il modello vive sul client e si sincronizza col backend

var model = this.store.find('user', 1); model.deleteRecord();// il modello non è più sullo store // ma va sincronizzato col backendmodel.save().catch(function() {// ops! Torniamo indietro model.rollback();});

StoreLo store astrae il backend

Il modello vive sul client e si sincronizza col backend

var model = this.store.find('user', 1); model.deleteRecord();// il modello non è più sullo store // ma va sincronizzato col backendmodel.save().catch(function() {// ops! Torniamo indietro model.rollback();});

La configurazione dello store (con gli adapters e serializzatori) permette di lavorare con ogni backend (anche legacy!)

Definire un modello 1 import DS from 'ember-data'; 2 3 export default DS.Model.extend({ 4 name: DS.attr('string'), 5 surname: DS.attr('string'), 6 is_admin: DS.attr('boolean'), 7 8 roles: DS.hasMany('roles', { embedded: 'always' }), 9 office: DS.belongsTo('office', { async: true }), 10 11 fullName: function() { 12 return this.get('name') + this.get('surname'); 13 }.property('name', 'surname'), 14 15 rolesList: function() { 16 return this.get('roles').map(function(role){ 17 return role.get('name'); 18 }); 19 }.property('roles.@each') 20 });

I tipi consentiti sono: string, number, boolean, date

Modelli

8 roles: DS.hasMany('roles', { embedded: 'always' }), 9 office: DS.belongsTo('office', { async: true }),

I modelli possono essere in relazione tra loro:

Modelli

8 roles: DS.hasMany('roles', { embedded: 'always' }), 9 office: DS.belongsTo('office', { async: true }),

I modelli possono essere in relazione tra loro:

Nel primo caso i dati sono forniti dal backend insieme al modello

Modelli

8 roles: DS.hasMany('roles', { embedded: 'always' }), 9 office: DS.belongsTo('office', { async: true }),

I modelli possono essere in relazione tra loro:

Nel primo caso i dati sono forniti dal backend insieme al modello

Nel secondo caso il modello contiene l’ID del modello associato e viene caricato in maniera

asincrona quando necessario con una chiamata specifica

Modelli

15 rolesList: function() { 16 return this.get('roles').map(function(role){ 17 return role.get('name'); 18 }); 19 }.property('roles.@each')

Le proprietà elaborate (computed properties) sono attributi bidirezionali non direttamente ottenuti attraverso il backend ma calcolati usando altri attributi (anche altre computed

properties)

ControllerI controller “preparano” il modello e altri dati per l’uso nei template

Controller

1 {{#if showForm}} 2 <form> 3 ... 4 </form> 5 <button {{action 'toggleFormVisibility'}}>Nascondi il form</button> 6 {{else}} 7 <button {{action 'toggleFormVisibility'}}>Mostra il form</button> 8 {{/if}}

I controller “preparano” il modello e altri dati per l’uso nei template

Controller

1 {{#if showForm}} 2 <form> 3 ... 4 </form> 5 <button {{action 'toggleFormVisibility'}}>Nascondi il form</button> 6 {{else}} 7 <button {{action 'toggleFormVisibility'}}>Mostra il form</button> 8 {{/if}}

1 import Ember from 'ember'; 2 3 export default Ember.Controller.extend({ 4 showForm: false, 5 6 actions: { 7 toggleFormVisibility: function() { 8 this.set('showForm', !this.get('showForm')); 9 } 10 } 11 });

I controller “preparano” il modello e altri dati per l’uso nei template

ControllerGli observer possono rimanere in “ascolto” di

cambiamenti negli attributi

Controller

1 import Ember from 'ember'; 2 3 export default Ember.Controller.extend({ 4 showForm: false, 5 6 formVisibilityObserver: function() { 7 console.log('Il form è visibile'); 8 }.observes('showForm'), 9 10 modelNameObserver: function() { 11 console.log('Il nome del modello è cambiato'); 12 }.observes('model.name') 13 });

Gli observer possono rimanere in “ascolto” di cambiamenti negli attributi

Action bubbling 1 <button {{action "like" user}}>Like</button>

Le azioni risalgono fino a trovare l’implementazione nel controller o nella rotta, fino alla rotta globale

(ApplicationRoute), ad esempio:

1 import Ember from 'ember'; 2 3 export default Ember.Route.extend({ 4 actions: { 5 like: function(user) { 6 // Implementazione 7 } 8 } 9 });

Azioni: rotta o controller?Le azioni possono essere definite sia nella rotta che

nel controller. Qual’è il posto giusto?

La convenzione è che la rotta ospiti azioni che hanno un impatto diretto sul modello, mentre il controller

gestisca le azioni che hanno impatto sui template e sul flusso di controllo

Componenti

Componenti

• Formate da un file js di logica e gestione azioni e un template

Componenti

• Formate da un file js di logica e gestione azioni e un template

• Forniscono componenti riusabili nel codice con una propria logica funzionale anche complessa

Componenti

• Formate da un file js di logica e gestione azioni e un template

• Forniscono componenti riusabili nel codice con una propria logica funzionale anche complessa

• Esistono anche gli helper che hanno un uso più banale (ad esempio formattare le date)

Componenti

Le componenti sostituiscono le viste delle vecchie versioni di Ember

• Formate da un file js di logica e gestione azioni e un template

• Forniscono componenti riusabili nel codice con una propria logica funzionale anche complessa

• Esistono anche gli helper che hanno un uso più banale (ad esempio formattare le date)

Componenti 1 {{#timetracker-weekly-day-column dayOfCurrentMonday=dayOfCurrentMonday dayOfWeek=5}}

Componenti

1 import Ember from 'ember'; 2 import moment from 'moment'; 3 4 export default Ember.Component.extend({ 5 classNames: ['col-md-1', 'text-center'], 6 7 isToday: function() { 8 return moment().format('YYYY-MM-DD') === moment(this.get( 9 'dayOfCurrentMonday')).add(this.get('dayOfWeek'), 'days'). 10 format('YYYY-MM-DD'); 11 }.property('dayOfCurrentMonday', 'dayOfWeek') 12 });

1 {{#timetracker-weekly-day-column dayOfCurrentMonday=dayOfCurrentMonday dayOfWeek=5}}

Componenti

1 import Ember from 'ember'; 2 import moment from 'moment'; 3 4 export default Ember.Component.extend({ 5 classNames: ['col-md-1', 'text-center'], 6 7 isToday: function() { 8 return moment().format('YYYY-MM-DD') === moment(this.get( 9 'dayOfCurrentMonday')).add(this.get('dayOfWeek'), 'days'). 10 format('YYYY-MM-DD'); 11 }.property('dayOfCurrentMonday', 'dayOfWeek') 12 });

1 {{#if isToday}} 2 {{dayOfWeek}} è oggi! 3 {{/if}}

1 {{#timetracker-weekly-day-column dayOfCurrentMonday=dayOfCurrentMonday dayOfWeek=5}}

Componenti

1 import Ember from 'ember'; 2 import moment from 'moment'; 3 4 export default Ember.Component.extend({ 5 classNames: ['col-md-1', 'text-center'], 6 classNameBindings: ['isToday:col-highlight'], 7 //qualcosa 8 });

1 {{yield}}

1 {{#timetracker-weekly-day-column dayOfCurrentMonday=dayOfCurrentMonday dayOfWeek=5}} 2 //qualcosa 3 {{/timetracker-weekly-day-column}}

Le componenti prendono anche dei blocchi in input

Addon

emberaddons.com

ember install <addon>

Aggiungono funzionalità all’applicazione, ad esempio template grafici (bootstrap), autenticazione, librerie (moment.js, datepicker), paginazione, animazioni,

librerie personali, ecc.

Risorse utili• guides.emberjs.com • discuss.emberjs.com • fromrailstoember.com • ember-cli.com • Ember.js su StackOverflow • emberwatch.com • Video da EmberConf 2015