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

Mastering Ember

Mastering Ember

Slides for the Mastering Ember Class

Avatar for Kevin Rockwood

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