我有以下代码:
app.directive "ngDisableOnVar", ($compile) ->
restrict: "A"
terminal: true
priority: 1000
replace:false
scope: {}
compile: compile = (element, attrs) ->
cattr = attrs["ngDisableOnVar"]
element.attr("ng-class", "{'disabled': !#{cattr}}")
element.attr("ng-disabled", "!#{cattr}")
element.removeAttr("ng-disable-on-var")
pre: preLink = (scope, iElement, iAttrs, controller) ->
post: postLink = (scope, iElement, iAttrs, controller) ->
$compile(iElement)(scope)
我尝试将代码基于here给出的答案。基本上,我想要有以下内容:
<input ngDisableOnVar="someScopeVariable>
并将其替换为以下内容:
<input ng-class="{'disabled': !someScopeVariable}" ng-disabled="!someScopeVariable">
有些东西是错误的,因为即使我将它们应用于我的元素,它们也总是被禁用,即使范围变量的计算结果为true。我做错了什么?
编辑: 我创建了一个plunker,其中前两个按钮是使用ng-class和ng-disabled创建的,另外两个按钮应该通过使用该指令在它们上应用相同的东西。
以下是具有共享范围的plunker版本:http://plnkr.co/edit/TebCQL20ubh5AgJ6nMIl?p=preview
这是没有共享范围的人:http://plnkr.co/edit/CPm55MrHA8z6Bx4GbxoN?p=preview
问题是,没有共享范围的人不会更新。如何让它们更新,并且条件取决于作为参数传递的变量?
编辑#2:编辑#2: 我开始相信范围共享是这两个按钮应该采取行动的正确方式,而不是创建一个封装其中的两个按钮的新指令。不过100%肯定。答案 0 :(得分:5)
我会选择你的编辑#2,因为他们是相关的。如果我们将它们创建为单独的元素,我们需要以某种方式将相关元素传递给每个元素=&gt;当我们点击1按钮时,我们会更新自己以及相关元素。
我在这里修改了您的第一种方法:http://plnkr.co/edit/KgYIlATiw9xzTEZt9Jv1?p=preview
在这个例子中,我必须将相关元素传递给每个指令,这样当我们点击时我们可以更新自己和相关元素:
related-element="btnForward"
我在指令中做了一些修改:
scope: {
reactOn: "=", //use property binding instead of function binding
relatedElement:"@"
},
link: function(scope, element, attrs) {
scope.toggle = function(){
scope.reactOn = !scope.reactOn;//toggle current element
var relatedScope = $("#"+scope.relatedElement).scope();//get related element's scope and toggle it
relatedScope.reactOn = !relatedScope.reactOn;
}
//var cattr = attrs.ngDisableReactOn;
element.attr("ng-class", "{'disabled': !reactOn}"); //Use reactOn instead as this is the property of current scope
element.attr("ng-disabled", "!reactOn");
element.attr("ng-click", "toggle()");
element.removeAttr("ng-disable-react-on");
$compile(element)(scope);
}
我们不需要让事情变得复杂。只需创建一个普通指令来包装2个按钮。
myApp.directive("ngDisableReactOn", function($compile) {
return {
restrict: "A",
templateUrl:"ngDisableReactOn.html",
scope: {
can_go_back: "@"
},
link: function(scope, element, attrs) {
scope.goBack = function(){
scope.can_go_back = false;
}
scope.goFwd = function(){
scope.can_go_back = true;
}
}
}
});
模板:
<input type="button" value="go back" ng-click="goBack()" ng-class="{'disabled': !can_go_back}" ng-disabled="!can_go_back">
<input type="button" value="go fwd" ng-click="goFwd()" ng-class="{'disabled': can_go_back}" ng-disabled="can_go_back">
另一种解决方案是将父指令创建为容器。这是我最喜欢的解决方案。使用这种方法,您可以自由更改指令的内部内容,例如添加更多按钮,更多文本,....(不需要硬编码模板)父指令作为管理器工作确保一次只有一个活跃的孩子:
myApp.directive("ngDisableReactOnContainer", function() { //Container directive to manage all child directives
return {
restrict: 'EA',
replace: true,
transclude: true,//Use transclusion to move inner content to the template
template: '<div ng-transclude></div>',
controller: function() {
var children = [];
this.selectChild = function(activeChild) { //ensure that only 1 child is active at a time
activeChild.active = true;
angular.forEach(children, function(child) {
if (child != activeChild) {
child.active = false;
}
});
}
this.addChild = function(child) {
children.push(child);
}
}
};
});
myApp.directive("ngDisableReactOn", function($compile) {
return {
restrict: "A",
scope:{
active:"@"
},
require: '^?ngDisableReactOnContainer',
link: function(scope, element, attrs, controller) {
scope.active = scope.active === 'true';
controller.addChild(scope);//register itself with the container
scope.select = function(){//When this element is clicked, inform the container to toggle all children accordingly.
controller.selectChild(scope);
}
//Add ng-class and ng-disabled based on your requirement.
element.attr("ng-class", "{'disabled': active}"); //Use active instead as this is the property of current scope
element.attr("ng-disabled", "active");
element.attr("ng-click", "select()");
element.removeAttr("ng-disable-react-on");
$compile(element)(scope);
}
}
});
使用这些指令很简单:
<div ng-disable-react-on-container>
<input ng-disable-react-on type="button" value="button 1" active="true" >
<input ng-disable-react-on type="button" value="button 2" >
<input ng-disable-react-on type="button" value="button 3" >
</div>
答案 1 :(得分:1)
这是一种非常难看的方式来演示如何在链接函数期间编译模板。这很难看,因为我没有解决范围变量的任何绑定问题。您可能希望隔离范围或设置双向绑定,但这应该为您提供如何访问范围以进行编译的要点。
app.directive('foo', function($compile) {
return function(scope, elem, attrs) {
var html;
if (scope.testVar)
html = '<input ng-class="{\'disabled\': !someScopeVariable}" ng-disabled="!someScopeVariable" />';
else
html = '<input />';
var htmlEl = angular.element(html),
compiledEl = $compile(htmlEl)(scope);
elem.replaceWith(compiledEl);
}
});
答案 2 :(得分:1)
您可以使用其他类似方法获得相同的效果。 Plunk here
而不是链接函数中的$compile
,您可以在指令中使用template
,在ng-disabled
中使用通过隔离范围绑定到父作用域变量的作用域中的变量。
答案 3 :(得分:-2)
您是否尝试删除var名称前的!
?
<input ng-class="{'disabled': someScopeVariable}" ng-disabled="someScopeVariable">