ng-repeat in combination with custom directive

隐身守侯 提交于 2019-11-27 03:11:12

问题


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.


回答1:


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" />');
            }
        };
});



回答2:


Put your ng-repeat in the template. You could modify attributes of element and accordingly in directive to determine if ng-repeat is needed, or what data to use inside the directive compiling

HTML(attribute):

<div ng-app="myApp" template-field></div>

JS:

angular.module('myApp', [])
    .directive('templateField', function () {
        return {          
            restrict: 'A',
            template:'<input type="text" value="{{field}" ng-repeat="field in [\'title\',\'body\']" />'            
        };
    });

DEMO: http://jsfiddle.net/GDfxd/3/

Also works as an element :

HTML(element):

<div ng-app="myApp" >
    <template-field/>
</div>

JS

angular.module('myApp', [])
    .directive('templateField', function () {
        return {          
            restrict: 'E',
            replace:true,
            template:'<input type="text" value="{{field}}" ng-repeat="field in [\'title\',\'body\']" />'

        };
    });

DEMO: http://jsfiddle.net/GDfxd/3/



来源:https://stackoverflow.com/questions/15344306/ng-repeat-in-combination-with-custom-directive

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!