我有以下代码:
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)
我试着将代码基于这里给出的答案.基本上,我想要以下内容:
有些东西是错误的,因为即使我将它们应用于我的元素,它们也总是被禁用,即使范围变量的计算结果为true.我究竟做错了什么?
编辑:我创建了一个plunker,其中前两个按钮是使用ng-class和ng-disabled创建的,另外两个按钮应该通过使用该指令应用相同的东西.
以下是具有共享范围的plunker版本:http://plnkr.co/edit/TebCQL20ubh5AgJ6nMIl?p = preview
这是没有共享范围的那个:http://plnkr.co/edit/CPm55MrHA8z6Bx4GbxoN?p = preview
问题是,没有共享范围的那个不会更新.如何让它们更新,并且条件取决于作为参数传递的变量?
编辑#2:我开始相信范围共享是这两个按钮应该采取行动的正确方式,而不是创建一个封装其中的两个按钮的新指令.不过100%肯定.
我会选择你的编辑#2,因为它们是相关的.如果我们将它们创建为单独的元素,我们需要以某种方式将相关元素传递给每个元素=>当我们单击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">
DEMO
另一种解决方案是将父指令创建为容器.这是我最喜欢的解决方案.使用这种方法,您可以自由更改指令的内部内容,例如添加更多按钮,更多文本,....(不需要硬编码模板)父指令作为管理员工作,以确保只有1个活动一次一个孩子:
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>
DEMO