Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ng-repeat in combination with custom directive

I'm having an issue with using the ng-repeat directive in combination with my own custom directive.

HTML:

<div ng-app="myApp">
  <x-template-field x-ng-repeat="field in ['title', 'body']" />
</div>

JS:

angular.module('myApp', [])
    .directive('templateField', function () {
        return {
            restrict: 'E',
            compile: function(element, attrs, transcludeFn) {
                element.replaceWith('<input type="text" />');
            }
        };
    });

See jSFiddle

The problem here is that nothing is replaced. What I'm trying to accomplish is an output of 2x input fields, with the 'x-template-field' tags completely replaced in the DOM. My suspicion is that since ng-repeat is modifying the DOM at the same time, this won't work.

According to this Stack Overflow question, the accepted answer seems to indicate this has actually worked in earlier versions of AngularJS (?).

Wouldn't element.html('...') work?

While element.html('...') actually injects the generated HTML into the target element, I do not want the HTML as a child element of the template tag, but rather replace it completely in the DOM.

Why don't I wrap my template tag with another tag that has the ng-repeat directive?

Basically, for the same reason as above, I don't want my generated HTML as a child element to the repeating tag. While it would probably work decently in my application, I would still feel like I've adapted my markup to fit Angular and not the other way around.

Why am I not using the 'template' property?

I haven't found any way to alter the HTML retrieved from the 'template' / 'templateUrl' properties. The HTML I want to inject is not static, it's dynamically generated from external data.

Am I too picky with my markup?

Probably. :-)

Any help is appreciated.

like image 936
vrutberg Avatar asked Mar 11 '13 17:03

vrutberg


People also ask

What can I use instead of NG-repeat?

You can consider using transclusion inside a custom directive, to achieve the behavior you are looking for without using ng-repeat.

What is Ng-repeat explain with example?

Definition and Usage The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.

Does ng-repeat create a new scope?

Each iteration of ng-repeat creates a new child scope, and that new child scope always gets a new property.


1 Answers

Your directive needs to run before ng-repeat by using a higher priority, so when ng-repeat clones the element it is able to pick your modifications.

The section "Reasons behind the compile/link separation" from the Directives user guide have an explanation on how ng-repeat works.

The current ng-repeat priority is 1000, so anything higher than this should do it.

So your code would be:

angular.module('myApp', [])
    .directive('templateField', function () {
        return {
            restrict: 'E',
            priority: 1001, <-- PRIORITY
            compile: function(element, attrs, transcludeFn) {
                element.replaceWith('<input type="text" />');
            }
        };
});
like image 95
rgarcia Avatar answered Sep 28 '22 12:09

rgarcia