Inheriting AngularJS directives to create reusable components Inheriting AngularJS directives to create reusable components angularjs angularjs

Inheriting AngularJS directives to create reusable components


I have also found most inheritance examples less than ideal but I have come up with a solution I think is clean and allows for fully inheritance.

As services and directives do not have prototype information available in them and extending Object directly is not good you will want to create a high level base class which could contain constants or very simple generic logic.

var BaseService = function() {};BaseService.prototype.toast = "french";BaseService.prototype.halloween = "scary";

Next lets create an abstract service (same logic for a directive) that can be extended.

module.factory('AbstractDirective', function(    $http, $q, $rootScope, $compile, $timeout) {    $.extend(this, new BaseService);    // Additional logic and methods should be appended onto 'this'    this.doStuff = function() {        alert("abstract function called");    };    this.halloween = 'fun';    // If adding a variable to the prototype of this extended class is desired    //     then this function would need to be extracted to its own variable    //     where the prototype values can be set before the function    //     is passed to the factory.     return this;}

Now lets create an actual implementation:

module.directive('DirectiveImpl', ['AbstractDirective', function(AbstractDirective) {    $.extend(this, AbstractDirective);    // A great part about this implementation pattern is that    //   DirectiveImpl does not need to pass anything to construct AbstractDirective.    // Meaning changes to AbstractDirective will have less impacts    //   on implementing classes.    this.doStuff = function () {        // Call        AbstractDirective.doStuff();        // Implement some logic additional        alert(this.toast + "Toast\nHalloween is " + this.halloween );    }    return this;}]);

for services use

module.factory

instead of

module.directive

When the doStuff function is call for DirectiveImpl you will get 2 alerts:

abstract function called

then

French ToastHalloween is fun

A similar pattern can be followed to allow full inheritance for controllers as well but there is a bit more to get that to work.


I used this implementation (based on Enzey's model) to get my directive to work as intended.

module.directive('DirectiveImpl', ['AbstractDirective', function(AbstractDirective) {    return {        controller: ['$scope','$element', function( $scope, $element ) {            $.extend($scope, AbstractDirective);            // A great part about this implementation pattern is that            //   DirectiveImpl does not need to pass anything to construct             //   AbstractDirective.            // Meaning changes to AbstractDirective will have less impacts            //   on implementing classes.            $scope.doStuff = function () {                // Call                AbstractDirective.doStuff();                // Implement some logic additional                alert($scope.toast + "Toast\nHalloween is " + $scope.halloween );            }         },        link: function( scope, element, opts ) {            scope.doStuff();        }    }}]);