Angularjs 当replace=true时,如何防止角度指令中的属性重复
我发现指定Angularjs 当replace=true时,如何防止角度指令中的属性重复,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我发现指定replace:true的角度指令会将指令用法中的属性复制到模板呈现的输出中。如果模板包含相同的属性,则模板属性值和指令属性值将在最终输出中组合在一起 指令用法: <foo bar="one" baz="two"></foo> 指令: .directive('foo', function() { return { restrict: 'E', replace: true, template: '<div bar="{{ba
replace:true
的角度指令会将指令用法中的属性复制到模板呈现的输出中。如果模板包含相同的属性,则模板属性值和指令属性值将在最终输出中组合在一起
指令用法:
<foo bar="one" baz="two"></foo>
指令:
.directive('foo', function() {
return {
restrict: 'E',
replace: true,
template: '<div bar="{{bar}}" baz="baz"></div>',
scope: {
bar: '@'
},
link: function(scope, element, attrs, parentCtrl) {
scope.bar = scope.bar || 'bar';
}
};
})
指令('foo',函数(){
返回{
限制:'E',
替换:正确,
模板:“”,
范围:{
酒吧:“@”
},
链接:函数(作用域、元素、属性、parentCtrl){
scope.bar=scope.bar | |“bar”;
}
};
})
输出:
<div bar="one " baz="two baz" class="ng-isolate-scope"></div>
bar=“one”
中的空格和baz
中的多个值都会导致问题。有没有办法改变这种行为?我意识到我可以在指令中使用非冲突属性,并在输出中同时具有模板属性和非冲突属性。但我希望能够使用相同的属性名称,并更好地控制模板的输出
我想我可以使用link
方法和element.removeAttr()
和element.attr()
。看起来应该有更好的解决办法
最后,我意识到有人在谈论弃用remove:true
,但保留它是有正当理由的。在我的例子中,我需要它用于使用转换生成SVG标记的指令。详情请参见此处:
不,没有什么好的声明方式来告诉Angular在移植到模板中时应该如何合并或操作
x
属性
Angular实际上直接将属性从源元素复制到目标元素(除了少数例外),并合并属性值。您可以在Angular编译器的函数中看到这种行为
由于无法更改该行为,因此可以通过指令定义的compile
或link
属性对属性及其值进行控制。对于您来说,在编译阶段而不是链接阶段进行属性操作更有意义,因为您希望在任何链接函数运行时这些属性都“准备就绪”
您可以这样做:
.directive('foo', function() {
return {
// ..
compile: compile
// ..
};
function compile(tElement, tAttrs) {
// destination element you want to manipulate attrs on
var destEl = tElement.find(...);
angular.forEach(tAttrs, function (value, key) {
manipulateAttr(tElement, destEl, key);
})
var postLinkFn = function(scope, element, attrs) {
// your link function
// ...
}
return postLinkFn;
}
function manipulateAttr(src, dest, attrName) {
// do your manipulation
// ...
}
})
了解您希望如何合并这些值会很有帮助。模板优先,元素优先,还是需要某种合并 由于我只能做一个假设,下面的代码假设您希望从元素上存在的模板中删除属性
.directive('foo', function() {
return {
restrict: 'E',
replace: true,
template: function(element, attrs) {
var template = '<div bar="{{bar}}" baz="baz"></div>';
template = angular.element(template);
Object.keys(attrs.$attr).forEach(function(attr) {\
// Remove all attributes on the element from the template before returning it.
template.removeAttr(attrs.$attr[attr]);
});
return template;
},
scope: {
bar: '@'
}
};
})
指令('foo',函数(){
返回{
限制:'E',
替换:正确,
模板:函数(元素、属性){
var模板=“”;
模板=角度元素(模板);
Object.key(attrs.$attr).forEach(function(attr){\
//在返回模板之前,从模板中删除元素上的所有属性。
template.removeAttr(attrs.$attr[attr]);
});
返回模板;
},
范围:{
酒吧:“@”
}
};
})
这是一个设计冲突
replace
只能与简单的
一起使用,不能使用属性。如果您需要这些属性,应该将它们传递给指令,而不是被替换的元素。@DaveAlperovich您能详细说明一下您的意思吗,任何更深入地描述您的问题的文档或链接?我希望在元素中传递属性,以便可以设置隔离范围,但我不希望输出这些属性。只应输出模板中的属性。我必须使用replace
,因为我使用的是SVG标记。我希望元素中的属性传递给用于设置隔离范围的指令,但我不希望这些属性包含在输出中。只应输出模板中的属性。谢谢你的解决方案,我想它会有用的!感谢您确认angular没有声明性的方式来做我想做的事情,并分享了一个建议的解决方案。我希望避免使用编译函数,但也许它最适合我的需要。