Angular scope.watch 在指令中不起作用

Posted

技术标签:

【中文标题】Angular scope.watch 在指令中不起作用【英文标题】:Angular scope.watch not working in directive 【发布时间】:2016-09-14 13:39:25 【问题描述】:

我有一个观察列表的角度指令,然后在编辑列表时创建自定义选择。我有这个在一个页面上工作,但它拒绝在另一个页面上工作。我不知道为什么 - 但是当列表发生变化时,手表似乎没有捕捉到。

我在这里重现了错误 - http://codepen.io/jagdipa/pen/Ramjez - 有人可以帮忙吗?!

angular.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('AppCtrl', function($scope) 
  $scope.clearValue = function() 
    $scope.myModel = undefined;
  ;
  $scope.save = function() 
    alert('Form was valid!');
  ;

  var Titles =["Title":"Mr","Title":"Master","Title":"Miss","Title":"Mrs"];
  $scope.titles = Titles;

);





module MyApp.Directives 

    interface TcSelectListScope extends ng.IScope 
        sourceList: any[];
        sourceListKey: string;
        sourceListValue: string;
    

    export class TcSelectListController 
        static $inject = [];

        constructor() 
        

    

    export class TcSelectList 
        public restrict = "A";
        public require = ["ngModel", "^form", '^^mdInputContainer', "select"];
        public controller = TcSelectListController;
        public controllerAs = 'selectController';
        public scope = 
            sourceList: "="
        

        constructor(private $compile: ng.ICompileService) 
        

        public compile(tElement, tAttributes) 
            var $compile = this.$compile;
            var _cacheService = this.cacheService;

            return function postLink(scope, element, attrs, controller) 
                var ngModelCtrl = controller[0];
                var mdInputContainerCtrl = controller[2];
                var selectCtrl = controller[3];
                console.log(selectCtrl);



              /*if (scope.sourceList == undefined)
                
                  scope.sourceList = [];
                */
                scope.$watch(scope.sourceList, scope.onModelChanged, true);
                //scope.$watchCollection(scope.sourceList, scope.onModelChanged);

                scope.onModelChanged = () => 
                    console.log('tc select list directive 2');
                    console.log(scope.sourceList);

                    if (attrs.sourceListKey == undefined) 
                        throw ("The source-list-key needs to be defined for tc-select-list");
                    
                    if (attrs.sourceListValue == undefined) 
                        throw ("The source-list-value needs to be defined for tc-select-list");
                    

                    var html = undefined;
                        html = buildSelect();

                    html = markSelected(html);
                    element.append(html);

                



                element.on("click", function () 
                    mdInputContainerCtrl.setHasValue(true);
                );

                element.bind("blur", function () 
                    if (ngModelCtrl.$viewValue == undefined) 
                        mdInputContainerCtrl.setHasValue(false);
                    
                );

                element.bind("change", function () 
                    mdInputContainerCtrl.setHasValue(true);
                );

                function buildSelect() 
                    var html = ``;

                    angular.forEach(scope.sourceList, (val, index) => 
                        var itemKey = scope.sourceList[index][attrs.sourceListKey];
                        var itemValue = scope.sourceList[index][attrs.sourceListValue];
                        var selected = ``;

                        html += `<option label="` + itemValue +
                            `" value="` + itemKey +
                            `" ` + selected +
                            ` >` + itemValue + ` < /option>`;
                    );

                    return html;
                

                function markSelected(html) 
                    if (ngModelCtrl.$modelValue != undefined && ngModelCtrl.$modelValue != null) 
                        html = html.replace(`value="` + ngModelCtrl.$modelValue + `"`,
                            `value="` + ngModelCtrl.$modelValue + `" selected`)
                    
                    return html
                
            
        

        static factory()  
            var directive = ($compile, cacheService) => new TcSelectList($compile, cacheService);
            directive.$inject = ["$compile"];
            return directive;
        
    

    angular.module("MyApp").directive("tcSelectList", TcSelectList.factory());



<div ng-controller="AppCtrl" layout="column" layout-align="center center" style="min-height: 300px;" ng-cloak="" class="selectdemoValidations" ng-app="MyApp">
  <form name="myForm">


    <p>Note that invalid styling only applies if invalid and dirty</p>
    <md-input-container class="md-block">
      <label>Favorite Number</label>
      <md-select name="myModel" ng-model="myModel" required="">
        <md-option value="1">One 1</md-option>
        <md-option value="2">Two</md-option>
      </md-select>
      <div class="errors" ng-messages="myForm.myModel.$error" ng-if="myForm.$dirty">
        <div ng-message="required">Required</div>
      </div>
    </md-input-container>
    <div layout="row">
      <md-button ng-click="clearValue()" ng-disabled="!myModel" style="margin-right: 20px;">Clear</md-button>
      <md-button ng-click="save()" ng-disabled="myForm.$invalid" class="md-primary" layout="" layout-align="center end">Save</md-button>
    </div>



    <md-input-container class="no-errors">
      <label>translations["Title"]</label>
      <div class="tc-select">
        <select name="title"
                tc-select-list
                ng-model="myModel.Title"
                source-list="titles"
                source-list-key="Title"
                source-list-value="Title"></select>
      </div>
    </md-input-container>
    <br/>
    titles
    <br/>       
    Title = myModel.Title
  </forms>




</div>

【问题讨论】:

【参考方案1】:

我找到了答案。原来以下行不起作用

scope.$watch(scope.sourceList, (newVal) => 

改成下面这个问题就解决了

scope.$watch('sourceList', (newVal) => 

【讨论】:

以上是关于Angular scope.watch 在指令中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Angular - 带有 controllerAs、bindToController 和 $scope.$watch 的指令

Angular $scope.$watch 用于仅从表单更改的变量(ng-model 指令)

AngularJS:$scope.$watch 没有更新从自定义指令上的 $resource 获取的值

秒味课堂Angular js笔记------$scope.$watch和$scope.$apply

将范围变量从控制器绑定到指令而不使用$ watch

ng -----监听变化($scope.$watch())