0

I'm using Daniel Crisps AngularJS Range Slider https://github.com/danielcrisp/angular-rangeslider and would like to extend his directive and modify the template.

His directive looks something like this (shortened for space):

angular.module('ui-rangeSlider', [])
.directive('rangeSlider', [
    function () {
       return {
          restrict: 'A',
          replace: true,
          template: ['<div class="ngrs-range-slider">',
                         '<div class="ngrs-runner">',
                           '<div class="ngrs-handle ngrs-handle-min"><i></i></div>',
                           '<div class="ngrs-handle ngrs-handle-max"><i></i></div>',
                           '<div class="ngrs-join"></div>',
                         '</div>',
                         '<div class="ngrs-value-runner">',
                           '<div class="ngrs-value ngrs-value-min" ng-show="showValues"><div>{{filteredModelMin}}</div></div>',
                           '<div class="ngrs-value ngrs-value-max" ng-show="showValues"><div>{{filteredModelMax}}</div></div>',
                         '</div>',
                       '</div>'].join('')
       }
    }
]);

I've been trying to use the suggestion in this question Extending Angular Directive by naming my directive the exact same name (shortened for example):

angular.module('myDirective', [])
.directive('rangeSlider', [
    function () {
        return {
            restrict: 'A',
            priority: 500,
            template: ['<div></div><div></div>'].join('')
        }
    }
]);

But am getting the following error: Multiple directives [rangeSlider, rangeSlider] asking for template on:

Has anyone run into this before and how would I go about updating the original template without modifying it in its source?

Edit: Had a an extra ')' in my example.

Community
  • 1
  • 1
spez86
  • 692
  • 1
  • 11
  • 24

3 Answers3

3

I found a method that allows you to modify a third-party template without touching their code and without any errors in AngularJS. It's a bit different from your attempt in that instead of defining a directive on your own module with the same name, you would decorate the directive on the third-party module using module.config() with $provide.

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.js"></script>
<script>
    // third-party code - cannot be modified
    angular.module('ui-rangeSlider', []).directive('rangeSlider', [function() {
        return {
            restrict: 'A',
            replace: true,
            template: '<div>base</div>'
        };
    }]);

    // this is your extension overriding the original template
    angular.module('ui-rangeSlider').config(['$provide', function($provide) {
        $provide.decorator('rangeSliderDirective', function($delegate) {
            var dir = $delegate[0];

            dir.template = ['<div>', dir.template, '<div>extended</div></div>'].join('');

            return $delegate;
        })
    }]);

    // this is your app
    angular.module('sample', ['ui-rangeSlider']);
</script>
<body ng-app="sample">
    <div range-slider></div>
</body>

You can try this live at https://jsfiddle.net/sjxwLe4k/4/ .

Daniel S.
  • 3,434
  • 22
  • 30
2

After a bunch of stackoverflow searching on how to extend AngularJS Directives (preferably in version 1.5.*), this is what worked for me.

Slightly modifying the decorator and $delegate from the above examples to work with Angular 1.5.8:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.js"></script>

<script>
        angular.module('ui-rangeSlider', []).directive('rangeSlider', [function() {
        return {
            restrict: 'A',
            replace: true,
            template: ['<div>base</div>'].join('')
        };
    }]);
    angular.module('myDirective', []).directive('rangeSlider', [function() {
        return {
            restrict: 'A',
            priority: 500,
            template: ['<div>extended</div>'].join('')
        }
    }]);
    angular.module('sample', ['ui-rangeSlider', 'myDirective'])
        .decorator('rangeSliderDirective', ['$delegate', function($delegate){
            console.log($delegate);
          $delegate.shift();
          return $delegate;
        }]);
</script>

<body ng-app="sample">
    <div range-slider></div>
</body>

You can see the above code working here:
https://jsfiddle.net/sjxwLe4k/6/

David
  • 66
  • 3
0

After looking at the your example. I am able to run this without any problems. I added both 'myDirective ' and 'ui-rangeSlider' to a empty app and i had no issues. I was able to remove the template from myDirective and it showed the ui-rangeSlider template.

html:

<div range-slider></div>

full example:

<!doctype html>
<html ng-app="sample">
  <head>
    <title>My Angular App</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
    <script>
        angular.module('sample', ['ui-rangeSlider', 'myDirective']);
        angular.module('ui-rangeSlider', [])
            .directive('rangeSlider', [
                function () {
                   return {
                      restrict: 'A',
                      replace: true,
                      template: ['<div class="ngrs-range-slider">',
                                     '<div class="ngrs-runner">',
                                       '<div class="ngrs-handle ngrs-handle-min"><i></i></div>',
                                       '<div class="ngrs-handle ngrs-handle-max"><i></i></div>',
                                       '<div class="ngrs-join"></div>',
                                     '</div>',
                                     '<div class="ngrs-value-runner">',
                                       '<div class="ngrs-value ngrs-value-min" ng-show="showValues"><div>{{filteredModelMin}}</div></div>',
                                       '<div class="ngrs-value ngrs-value-max" ng-show="showValues"><div>{{filteredModelMax}}</div></div>',
                                     '</div>',
                                   '</div>'].join('')
                   }
                }
            ]);
            angular.module('myDirective', [])
                .directive('rangeSlider', [
                    function () {
                        return {
                            restrict: 'A',
                            priority: 500,
                            template: ['<div></div>test<div></div>'].join('')
                        }
                    }
                ]);
    </script>
  </head>
  <body>
    <div range-slider></div>
  </body>
</html>
  • Really? Would you be able to provide an example? – spez86 Oct 28 '14 at 15:45
  • This solution doesn't work, because if you run it, you will see the same error in the JS console that the OP has reported. You can try this live at https://jsfiddle.net/sjxwLe4k/2/ . – Daniel S. Aug 19 '15 at 23:50