动态添加$ watch

时间:2015-10-23 20:44:43

标签: angularjs angularjs-watch

我有一个JSON数据集,每行包含一个输入值,一小段用于计算的JavaScript代码,以及一个小数值,它是eval()执行计算后输入值的结果。数据集将包含一行或多行。每个输入都将以HTML格式重复显示在页面上,并且小计的总和将作为总值和每个单独的小计值显示给用户。

我尝试使用$ watch并为转发器中的每一行添加一个,但是当用户更改输入值时,我似乎无法触发它们。

我已经创建了我的第一个Sample_Plunker ,以展示我想要实现的目标但没有成功。

不确定我是否也应该在这里发布代码,但是非常感谢任何帮助。

基本上我的HTML:

<div ng-controller="MainCtrl as MainCtrl" ng-init="MainCtrl.init()">
    <div ng-repeat="rule in MainCtrl.myCode">

        Input_{{$index}}: <input ng-model="rule.inpValue" type="number" />
        <!-- the following needs to reflect the result after eval() of myCode[?].code from JSON below -->
        Subtotal: {{rule.nSubTotal}}
        <br />
    </div>
    <br />

    <!-- the following should be a sum of all values above -->
    Total: {{MainCtrl.nTotal}}

</div>

这是我的示例数据和$ watch没有响应:

app.controller('MainCtrl', function($scope) {
    var _this = this;
    _this.nTotal = 0;
    // sample js code tht will be execuited later
    _this.myCode = [{
        "code": "_this.myCode.inpValue +2",
        "inpValue": 0,
        "nSubTotal": 0
    }, {
        "code": "_this.myCode.inpValue*3",
        "inpValue": 0,
        "nSubTotal": 0
    }, {
        "code": "_this.myCode.inpValue/5",
        "inpValue": 0,
        "nSubTotal": 0
    }];

    this.init = function() {
        $scope.$watch('MainCtrl.myCode[i].inpValue', function() {
            // debugger;

            // assuming if watch would fire, subtotal = eval( input ) 
            _this.nSubTotal = eval(_this.myCode[i].code);

            // I would also keep a running total at this point
            _this.nTotal = _this.nTotal + _this.myCode[i].nSubTotal;
        });
    }; //end init()
});

2 个答案:

答案 0 :(得分:4)

您的代码存在很多问题,但基本上回答您的问题,您可以通过循环遍历数组并为每个元素调用java.lang.NullPointerException at org.eclipse.nebula.visualization.xygraph.dataprovider.CircularBufferDataProvider.fireDataChange(CircularBufferDataProvider.java:474) at org.eclipse.nebula.visualization.xygraph.dataprovider.CircularBufferDataProvider.addSample(CircularBufferDataProvider.java:155) at prjNetAccelerator.XYGraphTransfer.addPoint(XYGraphTransfer.java:432) at prjNetAccelerator.AppGraphTransfer.addPoint(AppGraphTransfer.java:283) at prjNetAccelerator.AppGraphTransfer.pushPoint(AppGraphTransfer.java:187) at prjNetAccelerator.HtsLink.getStatusGui(HtsLink.java:456) at prjNetAccelerator.HtsLink.getStatusBasic(HtsLink.java:568) at prjNetAccelerator.ToolsTreeFolders.fetchFiles(ToolsTreeFolders.java:1351) at prjNetAccelerator.TimerFilesFetch.run(TimerFilesFetch.java:81) at java.util.TimerThread.mainLoop(Unknown Source) at java.util.TimerThread.run(Unknown Source) 一次,将监视应用于数组中的每个项目

我还强烈建议您使用实际函数而不是$scope.$watch来评估表达式。

&#13;
&#13;
eval()
&#13;
var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {

  var _this = this;
  _this.nTotal = 0;

  // sample js code tht will be execuited later
  _this.myCode = [{
    "code": function() { return this.inpValue + 2; },
    "inpValue": 0,
    "nSubTotal": 0
  }, {
    "code": function() { return this.inpValue * 3; },
    "inpValue": 0,
    "nSubTotal": 0
  }, {
    "code": function() { return this.inpValue / 5; },
    "inpValue": 0,
    "nSubTotal": 0
  }];

  function sum (values) {
      return values.reduce(function (a, b) { return a + b; }, 0);
  }

  this.init = function() {

    _this.myCode.forEach(function(code) {
      $scope.$watch(function() {
        return code.inpValue;
      }, function() {
        code.nSubTotal = code.code();
        _this.nTotal = sum(_this.myCode.map(function(c) { return c.nSubTotal; }));
      });
    });

  };

});
&#13;
&#13;
&#13;

答案 1 :(得分:1)

您的$watch未被触发,因为您正在观看一个表达式,该表达式将始终针对undefined评估为$scope。在观看一组项目进行更改时,您有几个选项:

  1. 每个项目单独$watch。效率不高,尤其是阵列很大时。
  2. 一个$watchGroup,它接受​​一组监视表达式。当表达式不均匀时很有用,例如不同对象的不同属性。
  3. 一个$watchCollection,用于观察单个物体。我认为这最适合你的情况。
  4. 另请注意,$watch*的第一个参数可以是一个返回您想要观看的值的函数。把它放在一起,你的观察者看起来像

    $scope.$watchCollection(function() {
      var aInputs = [];
      for (var i = 0, len = myCode.length; i < len; ++i) {
        aInputs.push(myCode[i].inpValue);
      }
      return aInputs;
    }, function() {
      // one of the inpValues in myCode has changed
      // need to re-compute nTotal
    });
    

    此外,我强烈建议您不要使用eval()并遵循JLRishe建议的使用功能。如果您绝对需要评估字符串表达式,可以使用Angular的$scope.$eval安全地执行此操作。这将根据范围和一组局部变量计算表达式。例如,

    $scope.$eval("inpValue + 2", { inpValue: 3 }) === 5;
    

    这是一个有效的Plunker。它使用$eval作为概念证明,但如果可以的话,再次使用普通函数。