不删除 replace: true
,如何在{* 1}}上使用ng-class
而不会导致与模板ng-class
发生错误/冲突?
目前,这会抛出以下Angular错误:
错误:语法错误:令牌' {'是第16列的意外标记 表达式[{custom:true} {custom:settings ==' custom',other: 设置=='其他'}]从[{custom:settings ==' custom',其他: 设置=='其他'}]
HTML
<div ng-app="MyApp" ng-controller="MyCtrl">
<setting settings="settings.someProperty"
ng-class="{custom: true}" />
</div>
JS
var myApp = angular.module('MyApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.settings = {
someProperty: ''
}
});
myApp.directive('setting', function() {
return {
restrict: 'E',
// Removing this is NOT an option
replace: true,
require: '^myCtrl',
template: '<div ng-class="{myclass:settings==\'custom\', other: settings==\'other\'}"><input type="radio" name="mySetting" ng-model="settings" value="other" />TEST</div>',
scope: {
settings: '=',
}
};
});
答案 0 :(得分:1)
研究角度编译,我们可以看到这是来自mergeTemplateAttributes函数的问题(你的jsFiddle使用的是v1.1.5,但这件作品甚至没有改变到v1。 5.0)。事实上,closed bug #7402引用了同样的问题。从该错误中引用@lgalfaso
我同意这是针对ng-class的一个问题,就像它在#7402 (comment)中所述的所有情况中都是一个问题一样。这是一个已知的错误和使用replace的指令限制:true
简而言之,如果没有一些解决方法,你就无法做到这一点。请注意,替换为DEPRECATED,因此您应该尝试删除replace: true
。但是,你可以破解它对你有利。
您可以将函数传递给template,而不是传递字符串。该函数将使用tElement和tAttrs执行。如果要完全替换该属性,将tAttrs.ngClass设置为空字符串将消除冲突。
template: function(tElement, tAttrs) {
tAttrs.ngClass="";
return '<div ng-class="{custom:settings==\'custom\', other: settings==\'other\'}"><input type="radio" name="mySetting" ng-model="settings" value="other" />TEST<br> <input type="radio" name="mySetting" ng-model="settings" value="" />{{settings}}</div>'
},
这是example fiddle。如果您将someProperty
更改为其他,则会看到它正确地将背景更改为黄色
另一方面,如果你想扩展/合并两个冲突的指令的属性值,它会更多地涉及到更多的开销。它仍然需要将tAttrs.ngClass设置为空字符串,但首先将其添加到ng-class中,如下所示:
template: function(tElement, tAttrs) {
var newNgClass = "{custom:settings==\'custom\', other: settings==\'other\'}";
var oldNgClass = tAttrs.ngClass;
var mergedNgClass = "extend(" + oldNgClass + "," + newNgClass + ")";
tAttrs.ngClass = "";
return '<div ng-class="' + mergedNgClass + '"><input type="radio" name="mySetting" ng-model="settings" value="other" />TEST<br> <input type="radio" name="mySetting" ng-model="settings" value="" />{{settings}}</div>'
},
link: function(scope) {
scope.extend = angular.extend;
}
不是合并两个角度表达式字符串,而是依赖于不在范围内的angular.extend,因此必须在链接函数中添加它。这是另一个example fiddle.
答案 1 :(得分:0)
我不认为这是最好的方法,但你可以认为这是一个黑客
HTML:
<div ng-app="MyApp" ng-controller="MyCtrl">
<setting settings="settings.someProperty"
ng-class="{custom: true," />
</div>
脚本:
var myApp = angular.module('MyApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.settings = {
someProperty: ''
}
});
myApp.directive('setting', function() {
return {
restrict: 'E',
// Removing this is NOT an option
replace: true,
require: '^myCtrl',
template: '<div ng-class="custom:settings==\'custom\', other: settings==\'other\'}"><input type="radio" name="mySetting" ng-model="settings" value="other" />TEST</div>',
scope: {
settings: '=',
}
};
});
https://jsfiddle.net/3jcmLh0t/10/
ng-class成为:{custom:true,custom:settings ==&#39; custom&#39;,other:settings ==&#39; other&#39;}。
自定义条件被定义为第二个将控制的自定义条件。
答案 2 :(得分:0)
这是另一种解决方案(没有任何黑客攻击)
请参阅此处的工作示例:https://jsfiddle.net/3gqjck49/4/
var myApp = angular.module('MyApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.settings = {
someProperty: ''
}
});
myApp.directive('setting', function() {
return {
restrict: 'E',
// Removing this is NOT an option
replace: true,
require: '^myCtrl',
template: '<div ng-class="{custom:settings==\'custom\', other: settings==\'other\'}"><input type="radio" name="mySetting" ng-model="settings" value="custom" />TEST<br> <input type="radio" name="mySetting" ng-model="settings" value="other" />{{settings}}</div>',
scope: {
settings: '=',
}
};
});