Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mastering Ember

Mastering Ember

Slides for the Mastering Ember Class

Kevin Rockwood

November 03, 2015
Tweet

More Decks by Kevin Rockwood

Other Decks in Technology

Transcript

  1. MASTERING EMBER INTRODUCTIONS ▸ What's your name? ▸ What do

    you do? ▸ What's your all time favorite video or board game? Ember Experience
  2. WHAT WE'LL COVER DAY 1 ▸ Ember CLI ▸ Templates

    ▸ Generators ▸ Ember Data ▸ Routing ▸ Helpers
  3. WHAT WE'LL COVER DAY 2 ▸ Computed Properties ▸ Components

    ▸ Services ▸ Forms and Persistence ▸ Transitions ▸ Substates
  4. WHAT WE'LL COVER DAY 3 - YOU CHOOSE! ▸ Deployment

    ▸ Fastboot ▸ Query Params ▸ Using Addons ▸ Building Addons ▸ Continuous Integration ▸ Wrapping jQuery Plugins ▸ Debugging ▸ The Run Loop ▸ JSON API ▸ Query Params ▸ Mobile Apps
  5. MASTERING EMBER INSTALL EMBER CLI > git --version git version

    2.6.2 > ember --version version: 1.13.8 ... > bower --version 1.6.3
  6. MASTERING EMBER CLONE THE REPO > git clone https://github.com/gaslight/mastering-ember.git Cloning

    into 'mastering-ember'... > cd mastering-ember/ > npm install ... > bower install ... github.com/gaslight/mastering-ember
  7. MASTERING EMBER - HOW TO HOW TO USE THIS REPO

    > git tag lab-1 lab-1-solution lab-2 ... > git checkout lab-1
  8. MASTERING EMBER - HOW TO EMBER CLI ▸ Toolchain for

    building Ember apps ▸ App server ▸ Test runner
  9. MASTERING EMBER - HOW TO EMBER INSPECTOR ▸ View route

    tree ▸ See Ember Data Attributes ▸ Log Deprecations ▸ Debug promisses ▸ See Rendering Performance
  10. MASTERING EMBER - HANDLEBARS HANDLEBARS TEMPLATES ▸ Represented as HTML

    ▸ Adds helpers for rendering dynamic content ▸ bound properties: ▸ {{model.property}} ▸ Loops: ▸ {{#each model as |thing|}}...{{/each}}
  11. TEXT ROUTING ▸ Ember IS the router ▸ Routes determine

    the UI ▸ The URL is the Single Source of Truth ▸ router.js declares routes ▸ the model hook:
  12. MASTERING EMBER - ROUTING DEFINING A ROUTE // app/routes/cars.js import

    Ember from 'ember'; export default Ember.Route.extend({ model() { return [ { make: "Ford", model: "Mustang" }, { make: "Tesla", model: "Model S" } ] } });
  13. MASTERING EMBER - ROUTING DEFINING A ROUTE // app/template/cars.hbs {{#each

    model as |car|}} <h1>{{car.make}} - {{car.model}}</h1> {{/each}} Ford - Mustang Tesla - Model S
  14. MASTERING EMBER GENERATORS > ember help generate version: 1.13.8 Requested

    ember-cli commands: ember generate <blueprint> <options...> Generates new code from blueprints. aliases: g
  15. MASTERING EMBER GENERATORS > ember generate route cars version: 1.13.8

    installing route create app/routes/cars.js create app/templates/cars.hbs updating router create cars installing route-test create tests/unit/routes/cars-test.js
  16. MASTERING EMBER - EMBER DATA EMBER DATA ▸ Persists data

    to the server ▸ Identity cache ▸ relationships hasMany(), belongsTo()
  17. MASTERING EMBER - EMBER DATA GENERATING A MODEL > ember

    generate model car version: 1.13.8 installing model create app/models/car.js installing model-test create tests/unit/models/car-test.js
  18. MASTERING EMBER MODEL ATTRIBUTES // app/models/car.js import DS from 'ember-data';

    export default DS.Model.extend({ make: DS.attr('string'), model: DS.attr('string'), year: DS.attr('number') });
  19. MASTERING EMBER FETCHING A MODEL // app/routes/cars.js import Ember from

    'ember'; export default Ember.Route.extend({ model() { return this.store.findAll('car'); } }); // GET JSON -> /api/cars
  20. MASTERING EMBER FOLLOW UP ▸ Adapters & Serializers ▸ DS.RESTAdapter

    ▸ JSON API: jsonapi.org ▸ getters and setters
  21. MASTERING EMBER - NESTED ROUTES NESTED ROUTES 1. Apple 2.

    Google 3. Microsoft Google Companies NASDAQ: GOOG Send all the data!
  22. MASTERING EMBER - NESTED ROUTES NESTED ROUTES 1. Apple 2.

    Google 3. Microsoft Google Companies NASDAQ: GOOG companies.js companies/show.js companies/show/stock-prices.js
  23. MASTERING EMBER - NESTED ROUTES NESTED ROUTES 1. Apple 2.

    Google 3. Microsoft Google Companies NASDAQ: GOOG companies.js companies/show.js
  24. MASTERING EMBER - NESTED ROUTES CREATING A NESTED ROUTE //

    app/router.js this.route('companies', { path: "/" }, function() { this.route('show', { path: "/companies/:id"}); });
  25. MASTERING EMBER DYNAMIC ROUTE PARAMS // app/routes/companies/show.js import Ember from

    'ember'; export default Ember.Route.extend({ model(params) { return this.store.findRecord('company', params.id); } }); // GET JSON -> /api/companies/1
  26. MASTERING EMBER - NESTED ROUTES <div class="row"> <div class="col-md-4"> {{#each

    model as |company|}} {{#link-to "companies.show" company}} {{company.name}} {{/link-to}} {{/each}} </div> <div class="col-md-8"> {{outlet} </div> </div> app/templates/companies.hbs <- app/templates/companies/show.hbs {{link-to}} {{outlet}}
  27. MASTERING EMBER - NESTED ROUTES MODEL RELATIONSHIPS // models/company.js export

    default DS.Model.extend({ stockPrices: DS.hasMany('stockPrice'), }); // models/stock-price.js export default DS.Model.extend({ company: DS.belongsTo('company'), });
  28. MASTERING EMBER - NESTED ROUTES NESTED ROUTES 1. Apple 2.

    Google 3. Microsoft Google Companies NASDAQ: GOOG Send all the data!
  29. MASTERING EMBER - NESTED ROUTES NESTED ROUTES 1. Apple 2.

    Google 3. Microsoft Google Companies NASDAQ: GOOG companies.js companies/show.js companies/show/stocks.js
  30. MASTERING EMBER - NESTED ROUTES DEFAULT CHILD ROUTES // app/router.js

    this.route('companies', { path: "/" }, function() { this.route('show', { path: "/companies/:id" } function() { this.route('stocks', { path: "/" }); }); });
  31. MASTERING EMBER - NESTED ROUTES MODELFOR() // app/route/companies/show/stocks.js export default

    Ember.Route.extend({ model() { let company = this.modelFor('companies.show') return this.store.query('stock-price', { company: company.get('id') }) } }); // GET JSON /api/stock-prices?company=1
  32. MASTERING EMBER - HELPERS HELPERS ▸ Simple input - output

    ▸ invoked with {{helper-name}} ▸ Must contain a "-" ▸ I prefer to prefix with an abbreviated namespace ▸ myapp-helper
  33. MASTERING EMBER - HELPERS REGISTER A HELPER // app/helpers/myapp-money.js import

    Ember from 'ember'; export function myappMoney(args) { return "$" + args[0]; } export default Ember.Helper.helper(myappMoney);
  34. MASTERING EMBER - COMPUTED PROPERTIES COMPUTED PROPERTIES ▸ Allow values

    to be calculated from other values ▸ Recompute when dependent values change
  35. MASTERING EMBER - HELPERS DECLARING A COMPUTED PROPERTY // models/artist.js

    import Ember from 'ember'; let { computed } = Ember; export default DS.Model.extend({ firstName: attr('string'), lastName: attr('string'), fullName: computed('firstName', 'lastName', function() { return this.get('firstName') + this.get('lastName'); }) });
  36. MASTERING EMBER - HELPERS THIS ALSO WORKS (BUT I DON'T

    RECOMMEND IT) // models/artist.js import Ember from 'ember'; let { computed } = Ember; export default DS.Model.extend({ firstName: attr('string'), lastName: attr('string'), fullName: function() { return this.get('firstName') + this.get('lastName'); }.property('firstName', 'lastName') });
  37. MASTERING EMBER - COMPONENTS COMPONENTS ▸ Encapsulate reusable pieces of

    behavior ▸ Similar to helpers, but can hold state and handle user actions ▸ Isolated - state is passed down, actions bubble up ▸ Can have a template ▸ Compatible with the Web Component spec ▸ Must contain a "-"
  38. MASTERING EMBER - COMPONENTSS COMPONENTS 1. Apple 2. Google 3.

    Microsoft Google Companies NASDAQ: GOOG components/price-change
  39. MASTERING EMBER - COMPONENTS COMPONENT TEMPLATE // templates/components/price-change.hbs <span class="{{isUp

    arrow-up:arrow-down}}"></span> <span>{{change}} ({{changePercentage}}%)</span>
  40. MASTERING EMBER - COMPONENTS COMPONENT JS // components/price-change.js export default

    Ember.Component.extend({ classNames: ['price-change'], classNameBindings: ["isUp:up:down"], click() { // Do Something } });
  41. MASTERING EMBER - COMPONENTS OUTPUT model() { return { open:

    712.78, current: 707.64 }; } {{price-change open=model.open current=model.current}} <div class="price-change down"> <span class="arrow-down"></span> <span>-5.14 (0.72%)</span> </div>
  42. MASTERING EMBER - COMPONENTS YIELDING {{#myapp-reveal}} <h1> I'm within a

    component! But I can still call {{model}} </h1> {{/myapp-reveal}}
  43. MASTERING EMBER - COMPONENTS YIELDING // components/myapp-reveal.js export default Ember.Component.extend({

    isRevealed: false, actions: { toggleRevealed() { this.toggleProperty('isRevealed'); } } });
  44. MASTERING EMBER - SERVICES SERVICES ▸ Hold state that isn't

    directly tied to the DOM ▸ Can wrap external APIs (Geolocation, LocalStorage) ▸ Can be used to communicate between objects ▸ Made available through dependency injection ▸ Singletons this.store is a service
  45. MASTERING EMBER - SERVICES DEFINING A SERVICE // services/cart.js export

    default Ember.Service.extend({ items: [], add(item) { this.get('items').pushObject(item); }) });
  46. MASTERING EMBER - SERVICES INJECTING A SERVICE // components/myapp-cart.js export

    default Ember.Component.extend({ cart: Ember.inject.service() }); // templates/components/myapp-cart.hbs {{#each cart.items as |item|}} {{item.name}} - {{item.price}} {{/each}}
  47. MASTERING EMBER - ACTIONS ACTIONS ▸ Handle click events (by

    default) ▸ Can take parameters ▸ Events can be specified ▸ Can have modifier keys ▸ Default browser behavior can be prevented
  48. MASTERING EMBER - ACTIONS THE ACTION HELPER IN ACTION <button

    {{action "create" model}}>Create</button> <button {{action "create" on="mouseUp"}}>Create</button> <a {{action "create" preventDefault="true"}}>Create</a> <button {{action "create" allowedKeys="alt"}}>Create</button>
  49. MASTERING EMBER - ACTIONS HANDLING ACTIONS ▸ Define an actions

    property ▸ Name of function maps to action name ▸ Can be on components, controllers, and routes ▸ Bubble up until they are handled ▸ Can be sent with send
  50. MASTERING EMBER - INPUT HELPERS INPUT HELPERS ▸ Create inputs

    bound to model properties ▸ Helpers for input and textarea ▸ Have properties for most HTML attributes
  51. MASTERING EMBER - INPUT HELPERS INPUT HELPERS {{input type="text" value=model.firstName

    size=“50”}} {{input value=model.lastName disabled=entryNotAllowed}} {{input type="checkbox" checked=model.isAdmin}} {{textarea value=model.someText }}
  52. MASTERING EMBER - PERSISTING DATA PERSISTING DATA ▸ .save() on

    model objects ▸ returns a promise ▸ call .then() and pass success handler, error handler
  53. MASTERING EMBER - PERSISTING DATA EMBER DATA ▸ store.createRecord("type", attrs)

    ▸ in an unsaved state ▸ model.get("isNew") tells you if its saved
  54. MASTERING EMBER - PERSISTING DATA LAB 9: CREATE ALBUMS ▸

    Add the route ▸ Create the template ▸ set the artist for the album ▸ remember our friend modelFor ▸ Implement an action ▸ Make the test pass!
  55. MASTERING EMBER - ADD-ONS ADD-ONS ▸ Are npm packages ▸

    have a keyword “ember-addon” ▸ Can be in-repo-addons ▸ Or published to npm registry
  56. MASTERING EMBER - ADD-ONS ENTRY POINT ▸ index.js by default

    ▸ exports an object ▸ name ▸ included ▸ before ▸ after ▸ defaultBlueprint
  57. MASTERING EMBER - ADD-ONS ADDON DIRECTORY ▸ everything under this

    is add-on namespace ▸ your code should go here ▸ projects using add-on need to import explicitly
  58. MASTERING EMBER - ADD-ONS APP DIRECTORY ▸ contents are merged

    into client projects ▸ templates go here ▸ “stubs” can re-export to give access automatically
  59. MASTERING EMBER - ADD-ONS COMPONENT EXAMPLE // addon/components/magic-button.js import Ember

    from 'ember'; export default Ember.Component.extend({ tagName: 'button', click() { ... } });
  60. MASTERING EMBER - ADD-ONS STUB EXAMPLE // app/components/magic-button.js import MagicButton

    from 'magic-button/components/magic-button'; export default MagicButton;
  61. MASTERING EMBER - ADD-ONS LOCAL NPM DEVELOPMENT ▸ npm link

    in the package directory ▸ makes a symlink in your node_modules ▸ in client project ember install add-on just works
  62. MASTERING EMBER - ADD-ONS LAB 10 ▸ Make me-now-playing addon

    ▸ ember addon me-now-playing ▸ npm link <inside me-no-playing> ▸ npm link me-now-playing <inside mastering-ember> ▸ add it to package.json
  63. MASTERING EMBER - PERFORMANCE OPTIMIZATIONS PERFORMANCE OPTIMIZATIONS ▸ Use Ember.run.later()

    over setTimeout() ▸ Use CSS transitions wherever possible ▸ Ember.computed.oneWay() ▸ Avoid observers wherever possible ▸ Optimize data fetching ▸ smoke-and-mirrors