在angularjs中以动态方式向WatchGroup添加值

时间:2015-04-23 14:57:29

标签: javascript angularjs angularjs-watch

我的角应用程序中有一个按钮,它会动态地为我的应用添加一个输入元素。我想将模型附加到此元素并将其放入观察组以跟踪任何更改。如果用户添加多个输入元素,我想在监视组中添加所有这些模型并跟踪哪个元素更改了其值。我怎么能这样做?

<body ng-app="myApp">

<div ng-controller="GpaController" > 
<form id="mform">
 <select name="grade" ng-model="grade" ng-options="key as key for (key,value) in gradePoints" ></select>    
<input type="number" min="1" max="4" ng-model="score">

</form>
<button type="button" ng-click="addElement()">Add</button>

</div>
<script type="text/javascript" src="./app/angular.min.js"></script>
<script type="text/javascript" src="./app/jquery-2.1.3.min.js"></script>
<script type="text/javascript">

angular.module('myApp', [])
.controller('GpaController', ['$scope', '$compile', function($scope, $compile){
    $scope.grade = 'A';
    $scope.score = 4;
    var gradePoints = { 'A': 4, 'A-': 3.7, 
                   'B+': 3.3, 'B': 3.0, 'B-': 2.7, 
                   'C+': 2.3, 'C': 2.0, 'C-': 1.7, 
                   'D': 1, 'F': 0 };
    $scope.gradePoints = gradePoints;
            $scope.$watchGroup(['grade', 'score'], function(){
                console.log($scope.grade)
                var n = $scope.gradePoints[$scope.grade] * $scope.score;
                    console.log(n);
            });
            $scope.addElement = function(){
                var val = '<div><select name="grade" ng-model="grade" ng-  options="key as key for (key, value) in gradePoints" > </select><input type="number" min="1" max="4" ng-model="score"><div>';
                var ele = $compile(val)($scope);
                    $("#mform").append(ele);
            }

}]);
</script>
</body>

2 个答案:

答案 0 :(得分:1)

您可以尝试以下方式检查哪个变量已更改。

$scope.$watchGroup(['grade', 'score'],
  function(newVal, oldVal) {
    var changed = ''
    if (newVal[0] != oldVal[0])
        changed = 'grade';
    if (newVal[1] != oldVal[1])
        changed = 'score';
});

有关详细信息,请参阅此SO Answer

<强>更新

要添加新值,您可以使用ng-repeat而不是添加元素

<强>标记

<form id="mform">
    <div ng-repeat="obj in objects">
        <select name="grade" ng-model="grade[obj]" 
         ng-options="key as key for (key,value) in gradePoints">
        </select>
        <input type="number" min="1" max="4" ng-model="score" />
    <div>
</form>

控制器

$scope.objects = ["1"]; //i have given sample, you could try something like this.
$scope.addElement = function(){ 
  $scope.objects.push($scope.objects.length + 1) 
}

答案 1 :(得分:1)

首先,你打破了Angular的#1规则。任何DOM操作或元素查找都不应该在属于指令的控制器中。

实际上,控制器中的所有逻辑实际上都属于指令。

.directive('gradePoints', function($parse) {
    return {
        template: function($element, $attrs) {
            return '<div><select name="grade" ng-model="' + $attrs.ngModel + '.grade" ng-options="key as key for (key, value) in gradePoints" > </select><input type="number" min="1" max="4" ng-model="' + $attrs.ngModel + '.score"> <div>',
        }
        link: function(scope, element, attrs) {
            $scope.grade = 'A';
            $scope.score = 4;
            var gradePoints = { 'A': 4, 'A-': 3.7, 
            'B+': 3.3, 'B': 3.0, 'B-': 2.7, 
            'C+': 2.3, 'C': 2.0, 'C-': 1.7, 
            'D': 1, 'F': 0 };

            $scope.$watchGroup(['grade', 'score'], function(){
                console.log($scope.grade)
                var n = $scope.gradePoints[$scope.grade] * $scope.score;
                console.log(n);
            });
        }
    }
});

然后在页面中添加新的grade-points指令并对$进行编译。

回答如何将此指令添加到页面的问题:

有很多方法可以解决这个问题,但更容易的是将指令放在ng-repeat中并且控制器在成绩数组中添加一个新条目。

控制器中的

$scope.rows = [];
$scope.addRow = function() {
    $scope.rows.push({});
}

在HTML中:

<button ng-click="addRow()"/>
<div ng-repeat="row in rows">
    <grade-point ng-model="row"/>
</div>