kasajian
5/21/2014 - 5:06 PM

shows how to repeat elements..

shows how to repeat elements..

Very simple directive that will repeat a particular element a given number of times:

<div repeat-x="5">Hello</div>
// Directive to repeat an element x number of times
angular.module('app').directive('repeatX', [function () {
    return {
        link: function (scope, element, attrs, controller) { // The link function gets called for every instance of this directive.
            for (var i = 0; i < Number(attrs.repeatX) - 1; i++) {
                // When we clone the element, we need to modify the attribute because it has repeat-x attribute.
                // We modify the attribute of the cloned element so that they repeat zero times.
                element.after(element.clone().attr('repeat-x', 0));
            }
        }
    };
}]);

But if you try to add binding, it's not going to work. The solution is to use the compile service:

    Text to repeat: <input type="text" ng-model="text" />
    <div repeat-x="5">{{text}}</div>
// Directive to repeat an element x number of times
angular.module('app').directive('repeatX', ['$compile', function ($compile) {
    return {
        link: function (scope, element, attrs, controller) { // The link function gets called for every instance of this directive.
            for (var i = 0; i < Number(attrs.repeatX) - 1; i++) {
                // When we clone the element, we need to modify the attribute because it has repeat-x attribute.
                // We modify the attribute of the cloned element so that they repeat zero times.
                element.after($compile(element.clone().attr('repeat-x', 0))(scope));
            }
        }
    };
}]);

The $compile service is pretty expensive. The alternative is to use the compiler function:

// Directive to repeat an element x number of times
angular.module('app').directive('repeatX', [function () {
    return {
        // The compile function is used to manipulate the dom prior to the link function executing
        // Note that unlike the link function, there's no scope or controller being passed in.
        // compile function runs once and affects all instances of the directive the same way.
        // The link function runs individually for each instance / usage of the directive in the HTML.
        compile: function (element, attrs) {
            for (var i = 0; i < Number(attrs.repeatX) - 1; i++) {
                // When we clone the element, we need to modify the attribute because it has repeat-x attribute.
                // We modify the attribute of the cloned element so that they repeat zero times.
                element.after(element.clone().attr('repeat-x', 0));
            }
        }
    };
}]);

The compile function can return a link function. Let's change the html and give a text attribute:

    Text to repeat: <input type="text" ng-model="text" />
    <div repeat-x="5" text="{{text}}">{{text}}</div>

Now observe the text attribute and when it changes to "Hello World", make it red.

// Directive to repeat an element x number of times
angular.module('app').directive('repeatX', [function () {
    return {
        // The compile function is used to manipulate the dom prior to the link function executing
        // Note that unlike the link function, there's no scope or controller being passed in.
        // compile function runs once and affects all instances of the directive the same way.
        // The link function runs individually for each instance / usage of the directive in the HTML.
        compile: function(element, attrs) {
            for (var i = 0; i < Number(attrs.repeatX) - 1; i++) {
                // When we clone the element, we need to modify the attribute because it has repeat-x attribute.
                // We modify the attribute of the cloned element so that they repeat zero times.
                element.after(element.clone().attr('repeat-x', 0));
            }

            // Optionally return a link function, which will be executed for each element.
            return function (scope, element, attrs, controller) {
                attrs.$observe('text', function(newValue) {
                    if (newValue === 'Hello World') {
                        element.css('color', 'red');
                    }
                });
            };
        }
    };
}]);