如何根据条件创建在目标元素上添加ng-class和ng-disabled的指令?

 mobiledu2502877427 发布于 2023-01-30 10:04

我有以下代码:

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%肯定.

1 个回答
  • 我会选择你的编辑#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

    2023-01-30 10:05 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有