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

Refactoring Angular Apps to Components (HelsinkiJS 11/15)

Refactoring Angular Apps to Components (HelsinkiJS 11/15)

Tero Parviainen

November 26, 2015
Tweet

More Decks by Tero Parviainen

Other Decks in Technology

Transcript

  1. Component is the main primitive. ! An atomic UI piece

    that is composable and reusable. Brian Ford, TXJS 2015
  2. @Component({ selector: 'my-confirmation', inputs: ['message'], outputs: ['ok'] }) @View({ template:

    ` <div> {{message}} <button (click)="ok()">OK</button> </div> ` }) class MyConfirmation { okEvents = new EventEmitter(); ok() { this.okEvents.next(); } } Interface Boundary: Inputs & Outputs UI Template Logic Angular 2 Components
  3. module.directive('myConfirmation', function() { return { scope: {}, bindToController: { message:

    '=', onOk: '&' }, controller: function() { }, controllerAs: 'ctrl', template: ` <div> {{ctrl.message}} <button ng-click="ctrl.onOk()"> OK </button> </div> ` } }); Interface Boundary: Inputs & Outputs UI Template Logic Angular 1 Approximation
  4. module.component('myConfirmation', { bindings: { message: '=', onOk: '&' }, controller:

    function() { }, template: ` <div> {{myConfirmation.message}} <button ng-click="myConfirmation.onOk()"> OK </button> </div> ` }); Interface Boundary: Inputs & Outputs UI Template Logic Angular 1.5 Approximation
  5. Image: Howard Lake Most Real Apps: Scope Soup ! Lots

    of ng-controller and ng-include ! No controller/template parity ! Data sharing through scope inheritance Rampant shared mutable state
  6. module.component(‘foobar', { scope: true, bindings: { visible: '=' }, controller:

    'FoobarCtrl', templateUrl: 'foobar.html' }); Replace external reference with bound input foobar.js After
  7. module.component('foobar', { scope: true, bindings: { visible: '=', language: '='

    }, controller: 'FoobarCtrl', templateUrl: 'foobar.html' }); Replace external reference with bound input foobar.js After
  8. module.component('foobar', { scope: true, bindings: { visible: '=', language: '=',

    onDelete: '&' }, controller: 'FoobarCtrl', templateUrl: 'foobar.html' }); foobar.js After Replace external function call with bound output
  9. foobar.html After Replace external function call with bound output <div

    ng-show="foobar.visible"> <p>{{foobar.getText(foobar.language)}}</p> <button ng-click="foobar.onDelete()"> Delete </button> </div>
  10. module.component('foobar', { scope: true, bindings: { visible: '=', language: '=',

    onDelete: '&' }, controller: 'FoobarCtrl', templateUrl: 'foobar.html' }); foobar.js Before Isolate Component
  11. 1 - Component Creation 2 - Data Flow Replace ng-include

    with Component Replace ng-controller with Component Move Markup to Component Template Adopt Template Root Controller to Component Replace External Reference with Bound Input Wrap Markup in Component Directive Replace External Function Call with Bound Output Isolate Component Replace State Mutation with Bound Outputs teropa.info/blog/2015/10/18/refactoring-angular-apps-to-components.html Replace Two-Way Binding with One-Way Binding