【问题标题】:Variable watch does not fire unless is an array除非是数组,否则变量手表不会触发
【发布时间】:2016-08-18 02:50:36
【问题描述】:

我有以下标记:

<div ng-controller="DataController as vm">
  <div ng-repeat="name in vm.users track by $index">
    {{name}}
  </div>
  <form name="form" validation="vm.errors">
    <input validator ng-model="vm.name" name="vm.name" placeholder="name" type="text" />
    <a href="#" ng-click="vm.add(vm.name)">Add</a>
  </form>
</div>

我有以下控制器:

function DataController($scope) {
  var vm = this;
  vm.name = "Mary";
  vm.users = ["Alice", "Peter"];
  vm.errors = 1;
  vm.add = function(name) {  
    vm.errors++;
    vm.users.push(name);    
  }  
}

每次添加用户时,我都会增加错误值。

我需要在指令中观察这个变量,所以我有:

app.directive("validation", validation);

function validation() {

  var validation = {
    controller: ["$scope", controller],
    restrict: "A",
    scope: {
     validation: "="
    }
  };

  return validation;

  function controller($scope) {
    this.errors = $scope.validation;
  } 
}  

app.directive("validator", validator);

function validator() {

  var validator = {
    link: link,
    replace: false,
    require: "^validation",
    restrict: "A"
  };

  return validator;

  function link(scope, element, attributes, controller) {
    scope.$watch(function() {
     return controller.errors;
   }, function () {
     console.log(controller.errors);
  });
}

console.log 显示初始值但不显示新值:
https://jsfiddle.net/qb8o006h/2/

如果我将 vm.errors 更改为一个数组,添加值并观察它的长度,那么它可以正常工作: https://jsfiddle.net/nprx63qa/2/

为什么我的第一个例子不起作用?

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    我更新了你的代码,你可以访问更新的属性 scope.vm.errors,如果你调试代码,你会看到属性 controller.errors 没有更新(在每个摘要之后,所有的手表都被调用重新评估它们)。如果您从范围访问属性错误,您可以添加 $scope.$watch 并使其工作。但是,我不建议在指令中使用 $scope.$watch。但这取决于你:

        var app = angular.module('app', []);
    
    app.controller("DataController", DataController);
    
    function DataController($scope) {
    
        var vm = this;
      vm.name = "Mary";
      vm.users = ["Alice", "Peter"];
      vm.errors = 1;
      vm.add = function(name) {  
          vm.errors++;
          vm.users.push(name);    
      }
    
    }
    
    app.directive("validation", validation);
    
    function validation() {
    
      var validation = {
        controller: ["$scope", controller],
        restrict: "A",
        scope: {
          validation: "="
        }
      };
    
      return validation;
    
      function controller($scope) {
        this.errors = $scope.validation;
      } 
    
    }  
    
    app.directive("validator", validator);
    
    function validator() {
    
      var validator = {
        link: link,
        replace: false,
        require: "^validation",
        restrict: "A"
      };
    
      return validator;
    
      function link(scope, element, attributes, controller) {
        scope.$watch(function() {
                    return scope.vm.errors
        }, function () {
          console.log(scope.vm.errors);
        });
      }
    
    }
    

    https://jsfiddle.net/kcvqn5kL/

    【讨论】:

    • 您会建议什么替代方案?基本上,每个验证器都将负责显示错误消息。我正在使用验证指令来定义哪个变量包含错误而不在所有验证器中重复它,因为它总是相同的......
    • 我正在使用一个指令,因为我想在我的整个应用程序中重用它。
    • 事实上,这就是我所拥有的并且只使用长度。
    • 让我修改代码并解决一些更好的问题
    • 你能检查一下这段代码吗? jsbin.com/jeciraqisi/edit?html,js,output 我正在考虑在模型中创建一个名为 errors 的对象,该对象将包含每个元素的所有错误。我还将属性元素添加到您的指令验证器中,因此您可以访问属性错误。您可以在指令或控制器中进行验证。我建议您对 $scope.$watch 中的元素进行所有验证,并为每个指令创建一个特殊的控制器,但这取决于您
    【解决方案2】:

    validation 指令controller 内的两个示例中,您都为errors 属性分配了对$scope.validation 值的引用。

    在第一个示例中,值为 numeric,因此 immutable - 1 - 无法修改参考值。 vm.add 修改控制器实例的属性值。然后将更改传播到validation 指令$scope.validation,但传播到validation 指令控制器实例$errors 属性。

    在第二个示例中,值是一个数组,因此 可变 - [] - 可以修改参考值。 vm.add 不会修改控制器实例的属性值。因此validation 指令控制器实例errors 属性值与Array 实例完全相同——因此它是length 更改。

    使用 不可变 值(如您的第一个示例)的一种方法是 $watch 一个控制器函数,如 this example

    function link(scope, element, attributes, controller) {
      scope.$watch(controller.errors, function (newValue) {
        console.log(newValue);
      });
    }
    

    其中controller.errors定义如下:

    function controller($scope) {
      this.errors = function(){ return $scope.validation; };
    }
    

    您可以找到以下有用的答案:

    【讨论】:

    • 有什么办法可以解决这个问题吗?我用一个数字给出了这个例子,但是如果我使用一个不改变长度的数组,那么它也不起作用。这就是我想让它发挥作用的原因
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2020-12-07
    • 1970-01-01
    • 2020-08-26
    • 2012-07-31
    相关资源
    最近更新 更多