将 $watch 附加到指令中的输入字段

Attach $watch to input field in directive

下面的指令旨在获取 <input> 标记的值并呈现确切数量的框。该指令需要限制为 E(糟糕的设计,但确实如此),所以看起来我需要找到某种方法将 $watch 附加到输入字段。

您可以在下面看到我的最佳尝试,或者至少是我想要完成的大致草图,但这只会在页面最初加载时触发。 alert 语句不会反映输入框中值的更改。

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="myApp">

<draw-boxes count="3"></draw-boxes>

<script>
var app = angular.module("myApp", []);
app.directive("drawBoxes", function() {
    var input = "<input type='text'></input>";
    var htmlCanvas = "<canvas width='800' height='800'></canvas>";
    var template = input + htmlCanvas;
    var linker = function(scope, el, attrs){
        scope.$watch(el.children()[0], function (v) {
                alert('value changed, new value is: ' + v);
                //Will do some canvas drawing here based on input
            });

    };
    return {
        restrict: "E",
        template : template,
        link: linker
    };
});
</script>

</body>
</html>

就个人而言,我会尝试将控制器附加到指令。

此外,输入字段需要附加一个唯一的 ng-model 值。

然后你的 $scope.$watch 可以在任何 $scope 值发生变化时检查输入字段的值是否发生变化。

像这样:

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="myApp">

<draw-boxes count="3"></draw-boxes>

<script>
var app = angular.module("myApp", []);
app.directive("drawBoxes", function() {
    var input = "<input type='text' ng-model='watchedInput'></input>";
    var htmlCanvas = "<canvas width='800' height='800'></canvas>";
    var template = input + htmlCanvas;

    return {
        restrict: "E",
        template : template,
        controller: function($scope) {
              $scope.$watch(function() {
                  // when a $scope value is changed, return the 
                  // value you want this watcher to watch
                  return $scope.watchedInput;  
              }, function(newValue) {
                  // if the value returned above is different from the
                  // previous value, this function will be invoked
                  // passing in the changed value as newValue
                  alert('value changed, new value is: ' + newValue);
              }, true);
        },
        scope: {},
        bindToController: true
    };
});
</script>

</body>
</html>

仅供参考:我还没有测试过这段代码,但想说明这个想法。

您可以在输入中使用 ng-change。这是一个例子:

var app = angular.module("myApp", []);

app.directive("drawBoxes", function() {
    var linker = function(scope, el, attrs){
        scope.valueChanged = '';
        scope.change = function() {
           scope.valueChanged = 'new value is ' + scope.value;
        };
    };
    return {
        restrict: "E",
        template : "<input type='text' ng-change=\"change()\" ng-model=\"value\"></input>"+
        "<span>{{valueChanged}}</span>" +
        "<canvas width='800' height='800'></canvas>",
        link: linker
    };

这是 jsfiddle 上的一个工作示例。