ng-repeat与自定义指令结合使用

时间:2013-03-11 17:01:20

标签: angularjs angularjs-ng-repeat

我遇到了将ng-repeat指令与我自己的自定义指令结合使用的问题。

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

请参阅jSFiddle

这里的问题是没有任何东西被替换。我想要完成的是2x输入字段的输出,在DOM中完全替换'x-template-field'标签。我怀疑是因为ng-repeat正在同时修改DOM,所以这不起作用。

根据this Stack Overflow问题,接受的答案似乎表明这实际上在早期版本的AngularJS(?)中有效。

element.html('...')不会工作吗?

虽然element.html('...')实际上将生成的HTML注入到目标元素中,但我不希望HTML作为模板标记的子元素,而是在DOM中完全替换它。

为什么我不将我的模板标签与另一个具有ng-repeat指令的标签包装在一起?

基本上,由于与上述相同的原因,我不希望生成的HTML作为重复标记的子元素。虽然它可能在我的应用程序中运行得很好,但我仍然觉得我已经调整了我的标记以适应Angular,而不是相反。

为什么我没有使用'template'属性?

我没有找到任何方法来改变从'template'/'templateUrl'属性中检索到的HTML。我想要注入的HTML不是静态的,它是从外部数据动态生成的。

我的标记太挑剔了吗?

可能。 : - )

感谢任何帮助。

2 个答案:

答案 0 :(得分:16)

您的指令需要使用更高的优先级在ng-repeat之前运行,因此当ng-repeat克隆元素时,它可以选择您的修改。

来自the Directives user guide的“编译/链接分离背后的原因”部分解释了ng-repeat的工作原理。

current ng-repeat priority是1000,所以高于此值的任何东西都应该这样做。

所以你的代码是:

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

答案 1 :(得分:3)

ng-repeat放入模板中。您可以修改元素的属性,并相应地在指令中确定是否需要ng-repeat,或者在指令编译中使用哪些数据

HTML(属性):

<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/

也作为一个元素:

HTML(元素):

<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/