5

I use angular 1.5 to develop my application and I am using .component(). I have three components and their controllers, all of which are quite similar. How can I extend the controller from comp1 to use it with comp2?

Each component in a separate js file:

comp1.js comp2.js comp3.js

Sofia Paixão
  • 309
  • 2
  • 16
Amine
  • 51
  • 1
  • 2
  • Is [this](http://stackoverflow.com/a/20230720/6263032) what you are looking for? – domyos Jun 28 '16 at 11:07
  • unfortunately this answer spoke about controller and not .component() – Amine Jun 28 '16 at 11:16
  • This has nothing to do with the component. In Angular 1.5 components are just a simpler way to write directives. The components/directive uses a controller the same way as you can annotate and html-tag with ng-controller. – domyos Jun 28 '16 at 11:19
  • What did you decide? One suggestion, though it requires a major head rethread, if you're still on AngularJS in 2020: Consider [moving your codebase to TypeScript](https://www.youtube.com/watch?v=LPX8mUfQ2MQ&list=PL-TLnxxt_AVE9dec6IU-0DSx6Oy5hsTCu&index=10), which helps to abstract that extension process for you. – ruffin Oct 02 '20 at 15:29

2 Answers2

1

You can extend component controllers from each other as well. Use the following approach:

Parent component (to extend from):

/**
 * Module definition and dependencies
 */
angular.module('App.Parent', [])

/**
 * Component
 */
.component('parent', {
  templateUrl: 'parent.html',
  controller: 'ParentCtrl',
})

/**
 * Controller
 */
.controller('ParentCtrl', function($parentDep) {

  //Get controller
  const $ctrl = this;

  /**
   * On init
   */
  this.$onInit = function() {

    //Do stuff
    this.something = true;
  };
});

Child component (the one extending):

/**
 * Module definition and dependencies
 */
angular.module('App.Child', [])

/**
 * Component
 */
.component('child', {
  templateUrl: 'child.html',
  controller: 'ChildCtrl',
})

/**
 * Controller
 */
.controller('ChildCtrl', function($controller, $parentDep) {

  //Get controllers
  const $ctrl = this;
  const $base = $controller('ParentCtrl', {$parentDep});

  //Extend
  angular.extend($ctrl, $base);

  /**
   * On init
   */
  this.$onInit = function() {

    //Call parent init
    $base.$onInit.call(this);

    //Do other stuff
    this.somethingElse = true;
  };
});

You can define new method in the child controller, overwrite existing methods, call the parent methods, etc. Works really well.

Adam Reis
  • 4,165
  • 1
  • 44
  • 35
1

I may suggest that you simply use services to share and compose components. You can then skip the complexities of worrying about .extend(), $controller, etc.

  angular
    .module('app')
    .factory('component.utils', function() {
       return {
         sharedProp: 'foo',
         sharedMethod: function() { return 'bar' }
       }
    })
    // components can all easily use functionality 
    // provided by one (or more) services, w/o 
    // needing a complicated inheritance model.
    .component('foo', {
      templateUrl: 'foo.html',
      controller: [
        'component.utils',
        function(utils) {
          this.$onInit = function() {
            this.prop = utils.sharedProp;
            utils.sharedMethod();
            // now do other foo things...
          }
        }
      ]
    })
    .component('bar', {
      templateUrl: 'foo.html',
      controller: [
        'component.utils',
        function(utils) {
          this.$onInit = function() {
            this.prop = utils.sharedProp;
            utils.sharedMethod();
            // now do other bar things...
          }
        }
      ]
    });

Inheritance has its place, but favoring composition over inheritance is usually the better solution. article.