Ember.js for a CakePHP Developer

Post on 17-May-2015

4,387 views 1 download

Tags:

description

Ember.js is a front end JavaScript MVC framework, but probably won't map to the exact same MVC patterns as CakePHP does on the server side. I cover the major features of Ember.js and attempt to make the connection to CakePHP classes where it applies.

transcript

EMBER.JS FOR ACAKEPHPDEVELOPER

EMBER.JSA framework for creating ambitious web applications.

1.0 RELEASED!

OBJECTS

EXTENDING/CREATING OBJECTSvar Person, p;

Person = Ember.Object.extend({ sayHello: function() { alert('Hello!'); }});

p = Person.create();

p.sayHello();

DATA BINDINGSvar Person, p;

Person = Ember.Object.extend({ message: 'Hello', responseBinding: 'message', yell: function() { alert(this.get('response')); }});

p = Person.create();

p.yell(); // alert('Hello')

p.set('message', 'Goodbye');

p.yell(); // alert('Goodbye')

COMPUTED PROPERTIESvar Person, p;

Person = Ember.Object.extend({ firstName: '', lastName: '', fullName: function() { return this.get('firstName') + ' ' + this.get('lastName'); }.property('firstName', 'lastName')});

p = Person.create({ firstName: 'Joey', lastName: 'Trapp' });

p.get('fullName'); // "Joey Trapp"

p.set('firstName', 'Connor');

p.get('fullName'); // "Connor Trapp"

CONVENTIONS

Type NameRoute this.resource('projects');Route (class) App.ProjectsRouteController App.ProjectsControllerView App.ProjectsViewTemplate Ember.TEMPLATES['projects']

TEMPLATES

TEMPLATES EMBEDDED IN HTML<script type="text/x-handlebars" data-template-name="project"> <h1>{{title}}</h1> <p>{{description}}</p></script>

Gets compiled on document read to:Ember.TEMPLATES['project'] = // compiled template function

TEMPLATES FILESIntegrate into build step and compile server side

// webroot/templates/projects/add.hbs

<form {{action save on="submit"}}> <label>Project Name</label> {{input type="text" value=name}}

<input type="submit" value="Save"></form>

Gets compiled with a build tool in development, and aspart of a production build step to:

Ember.TEMPLATES['projects/add'] = // compiled template function

BUILT IN HELPERS<div class="posts">{{#each post in controller}}

{{#if post.isPublished}} <h2>{{#link-to 'post' post}} {{post.title}} {{/link-to}}</h2> {{/if}}

{{else}}

<p>{{#link-to 'posts.new'}}Create the first post{{/link-to}}

{{/each}}</p></div>

And many more

ROUTER

DEFINING ROUTESApp.Router.map(function() { this.route('about'); // #/about});

Routes defined this way can not contain nested routes

DEFINING RESOURCESApp.Router.map(function() { this.resource('conferences'); // #/conferences});

Will render the conferences template in theapplication templates outlet.

NESTING RESOURCESApp.Router.map(function() { this.resource('conferences', function() { // #/conferences this.resource('cakefest'); // #/conferences/cakefest });});

Will render the cakefest template in the conferencestemplates outlet, which is rendered in the application

templates outlet.

DYNAMIC SEGMENTSApp.Router.map(function() { this.resource('conferences', function() { // #/conferences this.resource('conference', { path: ':name' }); // #/conferences/blah });});

By default, the segment value is available in the template.// conference template

<h1>{{name}}</h1><p>...</p>

NESTED ROUTESApp.Router.map(function() { this.resource('conferences', function() { // #/conferences this.route('new'); // #/conferences/new });});

Renders conferences/new template in theconferences templates outlet.

ROUTES

DEFINING DATA FOR TEMPLATEwindow.CONFERENCES = [ Em.Object.create({id: 1, name: 'cakefest' }), Em.Object.create({id: 2, name: 'embercamp' }), Em.Object.create({id: 3, name: 'jsconf' })];

var App = Ember.Application.create();

App.Router.map(function() { this.resource('conferences', function() { this.resource('conference', { path: '/:conference_id' }); });});

DEFINING ROUTE CLASSESApp.ConferencesRoute = Ember.Route.extend({ model: function() { return window.CONFERENCES; }});

App.ConferenceRoute = Ember.Route.extend({ model: function(params) { return window.CONFERENCES.findProperty( 'id', +params.conference_id ); }});

TEMPLATESconferences.hbs

<h1>Conferences</h1>

{{#each conf in controller}} {{#link-to 'conference' conf}} {{conf.name}} {{/link-to}}{{/each}}

conference.hbs<h1>{{name}} Conference</h1><p>{{desc}}</p>

OTHER CALLBACKSApp.ConferenceRoute = Ember.Route.extend({ model: function(params) { // Return data for the template },

setupController: function(controller, model) { // Receives instance of this controller and // the return value from model hook },

renderTemplate: function() { // Render template manually if you need to do // something unconventional }});

CONTROLLERS

Controllers are long lived in Ember*,

and are the default context for templates.

CONTROLLERDecorates a model, but has no special proxying behavior.

App.ApplicationController = Ember.Controller.extend({ search: '',

query: function() { var query = this.get('search'); this.transitionToRoute('search', { query: query }); }});

OBJECT CONTROLLERActs like an object and proxies to the model property.// In route class (this is the default behavior)setupController: function(controller, model) { controller.set('model', model);}

// Object ControllerApp.ConferenceController = Ember.ObjectController.extend({ isEven: function() { return this.get('name').length % 2 === 0; }.property('name')});

isEven calls this.get('name') which proxies tothis.get('model.name')

ARRAY CONTROLLERActs like an array, but actually performs on the methods

on the model property.App.ConferencesController = Ember.ArrayController.extend({ sortProperties: ['title']});

// conferences template{{#each conf in controller}} <div> <h1>{{conf.title}}</h1> </div>{{/each}}

Looping over controller in a template is actuallylooping over the model property*

VIEWS

Views are primarily used to handle browser events. Sincemany application actions can be handled with the action

helper and controller methods, you'll often not defineviews.

UTILIZE BROWSER EVENTSApp.ConferenceView = App.View.extend({ click: function(e) { alert('Click event was handled'); }});

SETTING VIEWS TAGIn the DOM, your templates are wrapped by a div with a

special id that Ember knows about.App.ConferenceView = Ember.View.extend({ tagName: 'section',});

The element wrapping the template will now be asection

HELPERS

REUSABLE TEMPLATE FUNCTIONSEmber.Handlebars.helper('capitalize', function(str) { return str[0].toUpperCase() + str.slice(1);});

And use the helpers in handlebars templates

<h1>{{title}}</h1><p>by {{capitalize firstName}} {{capitalize lastName}}</p>

QUESTIONS?@joeytrapp

github.com/joeytrapp

@loadsys

github.com/loadsys