Add directives from directive in AngularJS

后端 未结 7 1692
庸人自扰
庸人自扰 2020-11-22 10:02

I\'m trying to build a directive that takes care of adding more directives to the element it is declared on. For example, I want to build a directive that t

7条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-11-22 10:04

    Here's a solution that moves the directives that need to be added dynamically, into the view and also adds some optional (basic) conditional-logic. This keeps the directive clean with no hard-coded logic.

    The directive takes an array of objects, each object contains the name of the directive to be added and the value to pass to it (if any).

    I was struggling to think of a use-case for a directive like this until I thought that it might be useful to add some conditional logic that only adds a directive based on some condition (though the answer below is still contrived). I added an optional if property that should contain a bool value, expression or function (e.g. defined in your controller) that determines if the directive should be added or not.

    I'm also using attrs.$attr.dynamicDirectives to get the exact attribute declaration used to add the directive (e.g. data-dynamic-directive, dynamic-directive) without hard-coding string values to check for.

    Plunker Demo

    angular.module('plunker', ['ui.bootstrap'])
        .controller('DatepickerDemoCtrl', ['$scope',
            function($scope) {
                $scope.dt = function() {
                    return new Date();
                };
                $scope.selects = [1, 2, 3, 4];
                $scope.el = 2;
    
                // For use with our dynamic-directive
                $scope.selectIsRequired = true;
                $scope.addTooltip = function() {
                    return true;
                };
            }
        ])
        .directive('dynamicDirectives', ['$compile',
            function($compile) {
                
                 var addDirectiveToElement = function(scope, element, dir) {
                    var propName;
                    if (dir.if) {
                        propName = Object.keys(dir)[1];
                        var addDirective = scope.$eval(dir.if);
                        if (addDirective) {
                            element.attr(propName, dir[propName]);
                        }
                    } else { // No condition, just add directive
                        propName = Object.keys(dir)[0];
                        element.attr(propName, dir[propName]);
                    }
                };
                
                var linker = function(scope, element, attrs) {
                    var directives = scope.$eval(attrs.dynamicDirectives);
            
                    if (!directives || !angular.isArray(directives)) {
                        return $compile(element)(scope);
                    }
                   
                    // Add all directives in the array
                    angular.forEach(directives, function(dir){
                        addDirectiveToElement(scope, element, dir);
                    });
                    
                    // Remove attribute used to add this directive
                    element.removeAttr(attrs.$attr.dynamicDirectives);
                    // Compile element to run other directives
                    $compile(element)(scope);
                };
            
                return {
                    priority: 1001, // Run before other directives e.g.  ng-repeat
                    terminal: true, // Stop other directives running
                    link: linker
                };
            }
        ]);
    
    
    
    
        
        
        
        
    
    
    
    
        

提交回复
热议问题