Recursion in Angular directives

前端 未结 9 1506
不思量自难忘°
不思量自难忘° 2020-11-22 04:24

There are a couple of popular recursive angular directive Q&A\'s out there, which all come down to one of the following solutions:

  • manually incrementally \
9条回答
  •  醉话见心
    2020-11-22 04:53

    Inspired by the solutions described in the thread mentioned by @dnc253, I abstracted the recursion functionality into a service.

    module.factory('RecursionHelper', ['$compile', function($compile){
        return {
            /**
             * Manually compiles the element, fixing the recursion loop.
             * @param element
             * @param [link] A post-link function, or an object with function(s) registered via pre and post properties.
             * @returns An object containing the linking functions.
             */
            compile: function(element, link){
                // Normalize the link parameter
                if(angular.isFunction(link)){
                    link = { post: link };
                }
    
                // Break the recursion loop by removing the contents
                var contents = element.contents().remove();
                var compiledContents;
                return {
                    pre: (link && link.pre) ? link.pre : null,
                    /**
                     * Compiles and re-adds the contents
                     */
                    post: function(scope, element){
                        // Compile the contents
                        if(!compiledContents){
                            compiledContents = $compile(contents);
                        }
                        // Re-add the compiled contents to the element
                        compiledContents(scope, function(clone){
                            element.append(clone);
                        });
    
                        // Call the post-linking function, if any
                        if(link && link.post){
                            link.post.apply(null, arguments);
                        }
                    }
                };
            }
        };
    }]);
    

    Which is used as follows:

    module.directive("tree", ["RecursionHelper", function(RecursionHelper) {
        return {
            restrict: "E",
            scope: {family: '='},
            template: 
                '

    {{ family.name }}

    '+ '
      ' + '
    • ' + '' + '
    • ' + '
    ', compile: function(element) { // Use the compile function from the RecursionHelper, // And return the linking function(s) which it returns return RecursionHelper.compile(element); } }; }]);

    See this Plunker for a demo. I like this solution best because:

    1. You don't need an special directive which makes your html less clean.
    2. The recursion logic is abstracted away into the RecursionHelper service, so you keep your directives clean.

    Update: As of Angular 1.5.x, no more tricks are required, but works only with template, not with templateUrl

提交回复
热议问题