我试图在ng-repeat中动态添加不同的指令,但输出不会被解释为指令。
我在这里添加了一个简单示例:http://plnkr.co/edit/6pREpoqvmcnJJWzhZZKq
控制器:
$scope.colors = [{name:"red"}, {name: "blue"}, {name:"yellow"}];
指令:
app.directive("red", function () {
return {
restrict: 'C',
template: "RED directive"
}
});
HTML:
<ul>
<li ng-repeat="color in colors">
<span class="{{color.name}}"></span>
</li>
</ul>
如何使角度拾取通过ng-repeat输出的class
中指定的指令?
答案 0 :(得分:13)
我知道这是一个老问题,但谷歌把我带到了这里,我不喜欢这里的答案......对于应该简单的事情来说,它们看起来真的很复杂。所以我创建了这个指令:
*****新内容*****
我已经使这个指令更通用,支持解析(典型的角度值)“属性”属性。
/**
* Author: Eric Ferreira <http://stackoverflow.com/users/2954747/eric-ferreira> ©2016
*
* This directive takes an attribute object or string and adds it to the element
* before compilation is done. It doesn't remove any attributes, so all
* pre-added attributes will remain.
*
* @param {Object<String, String>?} attributes - object of attributes and values
*/
.directive('attributes', function attributesDirective($compile, $parse) {
'use strict';
return {
priority: 999,
terminal: true,
restrict: 'A',
compile: function attributesCompile() {
return function attributesLink($scope, element, attributes) {
function parseAttr(key, value) {
function convertToDashes(match) {
return match[0] + '-' + match[1].toLowerCase();
}
attributes.$set(key.replace(/([a-z][A-Z])/g, convertToDashes), value !== undefined && value !== null ? value : '');
}
var passedAttributes = $parse(attributes.attributes)($scope);
if (passedAttributes !== null && passedAttributes !== undefined) {
if (typeof passedAttributes === 'object') {
for (var subkey in passedAttributes) {
parseAttr(subkey, passedAttributes[subkey]);
}
} else if (typeof passedAttributes === 'string') {
parseAttr(passedAttributes, null);
}
}
$compile(element, null, 999)($scope);
};
}
};
});
对于OP的用例,你可以这样做:
<li ng-repeat="color in colors">
<span attributes="{'class': color.name}"></span>
</li>
或者将它用作属性指令:
<li ng-repeat="color in colors">
<span attributes="color.name"></span>
</li>
*****结束新内容******
/**
* Author: Eric Ferreira <http://stackoverflow.com/users/2954747/eric-ferreira> ©2015
*
* This directive will simply take a string directive name and do a simple compilation.
* For anything more complex, more work is needed.
*/
angular.module('attributes', [])
.directive('directive', function($compile, $interpolate) {
return {
template: '',
link: function($scope, element, attributes) {
element.append($compile('<div ' + attributes.directive + '></div>')($scope));
}
};
})
;
对于这个问题中的具体情况,可以稍微重写一下指令,使其将指令应用于一个类,如下所示:
angular.module('attributes', [])
.directive('directive', function($compile, $interpolate) {
return {
template: '',
link: function($scope, element, attributes) {
element.replaceWith($compile('<span class=\"' + attributes.directive + '\"></span>')($scope));
}
};
})
;
然后您可以在任何地方使用它并动态地按名称选择指令。像这样使用它:
<li ng-repeat="color in colors">
<span directive="{{color.name}}"></span>
</li>
我故意保持这个指令简单明了。您可能(并且可能会)必须重新编写它以满足您的需求。
答案 1 :(得分:9)
我在其中一个项目中面临同样的问题,你可以看到我如何在jsfiddle上解决这个问题
HTML:
<div class="page-wrapper" ng-controller="mainCtrl">
<div class="page">
<h3>Page</h3>
<ul>
<li ng-repeat="widget in widgets"><div proxy="widget" proxy-value="{{widget}}"></div></li>
</ul>
</div>
JS:
var app = angular.module('app',[]);
app.controller('mainCtrl', ['$scope', '$q', 'widgetAPI', function($scope, $q, widgetAPI) {
$scope.widgets = [];
widgetAPI.get().then(
function(data) {
$scope.widgets = data;
},
function(err) {
console.log("error", err);
}
);}])
.service('widgetAPI', ['$q', function($q) {
var api = {};
api.get = function() {
//here will be $http in real app
return $q.when(
[
{
component: 'wgtitle',
title: "Hello world",
color: '#DB1F1F',
backgroundColor: '#c1c1c1',
fontSize: '32px'
},
{
component: 'wgimage',
src: "http://cs425622.vk.me/v425622209/79c5/JgEUtAic8QA.jpg",
width: '100px'
},
{
component: 'wgimage',
src: "http://cs425622.vk.me/v425622209/79cf/S5F71ZMh8d0.jpg",
width: '400px'
}
]
);
};
return api;}])
.directive('proxy', ['$parse', '$injector', '$compile', function ($parse, $injector, $compile) {
return {
replace: true,
link: function (scope, element, attrs) {
var nameGetter = $parse(attrs.proxy);
var name = nameGetter(scope);
var value = undefined;
if (attrs.proxyValue) {
var valueGetter = $parse(attrs.proxyValue);
value = valueGetter(scope);
}
var directive = $injector.get(name.component + 'Directive')[0];
if (value !== undefined) {
attrs[name.component] = value;
}
var a = $compile(directive.template)(scope);
element.replaceWith(a);
}
}}])
.directive('wgtitle', function() {
return {
restrict: 'A',
scope: true,
replace: true,
template: '<h1 style="color:{{widget.color}}; font-size:{{widget.fontSize}}; background:{{widget.backgroundColor}}" >{{widget.title}}</h1>',
link: function(scope, element, attrs) {
}
}})
.directive('wgimage', function() {
return {
restrict: 'A',
scope: true,
replace: true,
template: '<img style="width:{{widget.width}}" src="{{widget.src}}"/>',
link: function(scope, element, attrs) {
}
}});
我希望它有用。
答案 2 :(得分:3)
我认为你不能仅仅将指令指定为类名 - 你需要再次通过$compile
运行它,这将导致递归错误的路径。
一个可能的解决方案概述于:AngularJS - how to have a directive with a dynamic sub-directive
如果它适用于您的用例,则可以使用模板:
<div ng-repeat='template in inner' ng-include='template'></div>