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

Living in a Component World

Chris Ball
February 21, 2016

Living in a Component World

You have probably heard by now that Components are the way forward in Ember. Component all the things! Routeable Components haven't landed yet, and in the meantime you want to make sure you're building things the right way.

This talk will focus on using Components as the major building blocks in your application. We'll discuss Data Down/Actions Up, how to handle parent/child components, yielding, closure actions, and helpers using some test-driven examples to guide the way.

Chris Ball

February 21, 2016

More Decks by Chris Ball

Other Decks in Programming


  1. Living in a Component World cball_ {{user-list}} {{profile-navigator}} {{gravatar-image}} {{signup-form}}

    {{comment-form as |form|}} {{#toggle-button}} hi {{else}} bye {{/toggle-button}} {{happy-user}} Component!
  2. cball_

  3. cball_

  4. How did we get here? cball_

  5. cball_ Why are components a good thing?

  6. cball_ They are reusable.

  7. cball_ They are isolated.

  8. cball_ They are easy to test.

  9. cball_ They eventually will be supported natively.

  10. Controllers cball_

  11. cball_ 2 Responsibilities

  12. cball_ 2 Responsibilities 1 - Decorate models for templates 2

    - Store state as a singleton
  13. cball_ 1 - Decorate models for templates Ember.Controller.extend({ sort: ['ordinal:desc'],

    sortedThings: Ember.computed.sort('things', 'sort') });
  14. cball_ 2 Responsibilities 1 - Decorate models for templates 2

    - Store state as a singleton
  15. cball_ this.set('someProperty', true); .. change route ... when you come

    back its still true! 2 - Store state as a singleton
  16. cball_ 1 - Decorate models for templates 2 - Store

    state as a singleton Components Services
  17. cball_ So when do controllers go away?

  18. cball_ 2 Major Blockers

  19. cball_ 1. Query Params

  20. cball_ 2. Routable Components

  21. Component Building Blocks cball_

  22. yield cball_

  23. cball_ {{#some-component}} This text gets inserted {{/some-component}} yield <div class="inside-component">

    {{yield}} </div>
  24. cball_ {{#some-component as |some thing|}} {{concat some.name 'crazy'}} {{/some-component}} yield

    <div class="inside-component"> {{yield some thing}} </div>
  25. cball_ {{#car-list cars=cars as |car|}} Amazing {{car.name}} {{else}} Show when

    I have no cars. {{/car-list}} yield to inverse {{#each cars as |car|}} {{yield car}} {{/else}} {{yield to="inverse"}} {{/each}}
  26. Parent / Child cball_

  27. cball_ {{!-- some-route/template.hbs --}} {{#custom-table as |table row|}} {{custom-column table=table

    name='foo'}} {{row.someProperty}} {{/custom-column}} {{/custom-table}} Parent/Child {{!-- custom-table/template.hbs --}} {{#each content as |row| {{yield this row}} {{/each}}
  28. cball_ Parent/Child didInsertElement() { this.get('table').registerColumn(this); }, willDestroyElement() { this.get('table').unregisterColumn(this); }

  29. Contextual Components cball_

  30. cball_ Contextual Components New in Ember 2.3, pass a hash

    to yield that contains a component
  31. cball_ Contextual Components {{!-- custom-table/template.hbs --}} {{#each content as |row|

    {{yield (hash row=(component 'crazy-row' table=this row=row)}} {{/each}} {{!-- some-route/template.hbs --}} {{#custom-table as |table|}} {{#table.row as |row|}} {{!-- something with row.someProperty --}} {{/table}} {{/custom-table}}
  32. Closure Actions cball_

  33. cball_ Closure Actions Solution to send action to (or through)

    parent components.
  34. cball_ Easy nested actions {{!-- some-route/template.hbs --}} {{my-component on-update-thing=(action 'doUpdate'

    thing)}} {{!-- parent-component/template.hbs --}} {{child-component on-update-thing=on-update-thing}} {{!-- child-component/template.hbs --}} <button {{action on-update-thing}}>Go!</button>
  35. cball_

  36. cball_ They can also return values! {{!-- thing/template.hbs --}} {{my-component

    on-update-thing=(route-action 'doUpdate')}} {{!-- thing/route.js --}} export default Ember.Route.extend({ actions: { doUpdate(thing) { return thing.save().then(() => doStuff()); } } });
  37. cball_ Basically, use closure actions all the time.

  38. cball_ One use looks a bit strange. {{!-- my-component/template.hbs --}}

    <button {{action (action 'doStuff')}}Go!</button>
  39. Dynamic Components cball_

  40. cball_ Dynamic Components {{!-- profile/template.hbs --}} <div class="profile"> {{component (concat

    userType '-profile')}} </div> {{!-- profile/template.hbs --}} <div class="profile"> {{component userProfileComponent}} </div>
  41. Helpers cball_

  42. cball_ Helpers {{!-- some-route/template.hbs --}} {{my-chart options=(options-from-data data) {{!-- some-route/template.hbs

    --}} {{if (eq user currentUser)}}
  43. How to Component cball_

  44. Enforce DDAA. cball_

  45. cball_ Data Down, Actions Up A way to reason about

    your app’s data flow.
  46. cball_ 2-way binding ◦

  47. cball_ Angle Bracket Components = Glimmer Components

  48. cball_ One way data flow by default.

  49. cball_ Prepare your apps for the future by enforcing DDAA!

  50. Don’t use attrs (yet). cball_

  51. Use closure actions. cball_

  52. Use the route-action helper. cball_

  53. cball_ route-action helper Allows you to use closure actions that

    target the Route.
  54. cball_

  55. cball_ {{!-- foo/template.hbs --}} {{foo-bar clicked=(route-action "updateFoo" "Hello" "world")}}

  56. Use dynamic Components cball_

  57. Use pods (not required, but helpful). cball_

  58. Make top-level Components. cball_

  59. Use helpers. cball_

  60. cball_ https://cdn.tutsplus.com/vector/uploads/legacy/qt/2011_QT/qt_26_wire_globe/preview.jpg Image Credits http://www.safetysign.com/images/catlog/product/large/X4526.png http://webcomponents.org/

  61. cball_ Thanks!