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

Putting Composability to Work

Putting Composability to Work

At the Ember NYC meetup

Avatar for Phil Gengler

Phil Gengler

February 26, 2016
Tweet

Other Decks in Technology

Transcript

  1. Using composition in Ember - Mixins - Template helpers (like

    “action”, “mut”, “hash”, and “component”)
  2. Using composition in Ember - Mixins - Template helpers (like

    “action”, “mut”, “hash”, and “component”) - Addons providing composable elements: • ember-truth-helpers • ember-composable-helpers • ember-cpm • ember-composability • etc.
  3. Composition (not) in Ember In 2013 there was a PR

    to add composable computed properties to Ember Merged into master behind a feature flag in January 2014 Removed from master in March 2014 https://github.com/emberjs/ember.js/pull/3696
  4. Benefits of composition • Easier to reason about small bits

    of code • Easier to comprehensively test smaller and separate bits of code
  5. Benefits of composition • Easier to reason about small bits

    of code • Easier to comprehensively test smaller and separate bits of code • Less repetition since you can reuse bits of code you’ve already written
  6. Multiple behaviors for routes - using inheritance // app/routes/authenticated-route.js export

    default Ember.Route.extend({ /* auth-related stuff here * / }); // app/routes/confirms-when-leaving.js export default Ember.Route.extend({ /* install/uninstall event handler */ }); // app/routes/super-awesome.js export default Ember.Route.extend({ /* super awesome stuff in here */ }); // app/routes/authenticated-and-confirms-when-leaving.js export default Ember.Route.extend({ /* repeat your auth-related code here */ /* install/uninstall "onbeforeunload" handler */ }); // app/routes/authenticated-and-super-awesome.js export default Ember.Route.extend({ /* repeat your auth-related code in here again */ /* repeat your super awesome stuff in here */ }); // app/routes/confirms-when-leaving-and-super-awesome.js export default Ember.Route.extend({ /* install/uninstall "onbeforeunload" handler */ /* continue to repeat your super awesome stuff in here */ }); // app/routes/authenticate-and-confirms-and-super-awesome.js export default Ember.Route.extend({ /* repeat your auth-related code yet again */ /* install/uninstall "onbeforeunload" handler */ /* and repeat your super awesome stuff in here AGAIN */ });
  7. Multiple behaviors for routes - using mixins // app/routes/actual-route.js import

    AuthenticatedRouteMixin from '../mixins/authenticated-route'; import ConfirmsWhenLeavingMixin from '../mixins/confirms-when-leaving'; export default Ember.Route.extend( AuthenticatedRouteMixin, ConfirmsWhenLeavingMixin, { // your route here }); // app/mixins/authenticated-route.js export default Ember.Mixin.create({ /* auth-related stuff here * / }); // app/mixins/confirms-when-leaving.js export default Ember.Mixin.create({ /* install/uninstall event handler */ }); // app/mixins/super-awesome.js export default Ember.Mixin.create({ /* super awesome stuff in here */ });
  8. Using the `action` and `mut` helpers // app/components/attendance-counter.js export default

    Ember.Component.extend({ leftCounter: 0, rightCounter: 0 }); {{! app/templates/components/attendance-counter.hbs }} Left line: {{leftCounter}} {{incrementer-button value=leftCounter updateValue=(action (mut leftCounter))}} <br> Right line: {{rightCounter}} {{incrementer-button value=rightCounter updateValue=(action (mut rightCounter))}} // app/components/incrementer-button.js export default Ember.Component.extend({ actions: { clicked() { this.sendAction('updateValue', this.get('value') + 1); } } }); {{! app/templates/components/incrementer-button.hbs }} <button type='button' onclick={{action 'clicked'}}>+</button>
  9. Contextual components From the Ember 2.3 release announcement: {{! app/templates/components/alert-box.hbs

    }} <div class="alert-box"> {{yield (hash close-button=(component 'alert-box-button' onclick=(action 'close')) )}} </div>
  10. Mixing mixins Given this setup, what do you think will

    be logged? // app/mixins/thing-one.js export default Ember.Mixin.create({ value: 0, didInsertElement() { let value = this.get('value'); console.log('thing-one: %s', value); } }); // app/mixins/thing-two.js export default Ember.Mixin.create({ value: 'abc', didInsertElement() { let value = this.get('value'); console.log('thing-two: %s', value); } }); // app/components/log-stuff.js import ThingOne from '../mixins/thing-one'; import ThingTwo from '../mixins/thing-two'; export default Ember.Component.extend(ThingOne, ThingTwo);
  11. Which of these is easier to understand? {{#if (or user.isAdmin

    (eq page.owner user.id))}} {{#if userCanEditPage}} or