检测谁更改模型(用户输入与控制器)angularjs

时间:2016-03-02 14:10:31

标签: javascript angularjs angularjs-directive angularjs-watch

我有一个连接到模型的输入。此外,输入具有$watch模型的指令。

模型有两种变化方式。

  1. 用户将输入文本框。
  2. 代码会改变它(无论是什么原因)
  3. 我的问题是

    有没有办法找出谁在指令中更改了模型,用户交互或代码?

    示例:

    angular.module('app', [])
    .controller('ctrl', function($scope) {
    
    })
    .directive('dir', function($rootScope){
      return {
        require: 'ngModel',
        link: function(scope, element, attrs) {
          $rootScope.logs = [];
          scope.$watch(attrs.ngModel, function() {
            // here I need to check if the change was from the UI or from the controller
            
            $rootScope.logs.push('change');
          });
        }
      }
    });
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
    <div data-ng-app="app" data-ng-controller="ctrl">
      <input type="text" data-ng-model="model" data-dir="" />
      <button data-ng-click="model = 'asd'">Set "model" to defferent value</button>
    
      {{model}}
      <hr />
      <h3>console <button data-ng-click="$root.logs = []">clear console</button></h3>
      <ul>
        <li data-ng-repeat="log in $root.logs track by $index" data-ng-bind="log"></li>
      </ul>
    </div>

    http://jsbin.com/vufawur/edit?html,js,output

    更新

    例2:

    angular.module('app', [])
    .controller('ctrl', function($scope, $timeout) {
      $timeout(function() {
          $scope.model = 'asd';
      }, 3000);
    })
    .directive('dir', function($rootScope){
      return {
        require: 'ngModel',
        link: function(scope, element, attrs) {
          $rootScope.logs = [];
          scope.$watch(attrs.ngModel, function() {
            // here I need to check if the change was from the UI or from the controller
    
            $rootScope.logs.push('change');
          });
        }
      }
    });
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
    <div data-ng-app="app" data-ng-controller="ctrl">
      ...wait until data "return from the server"<br />
      <input type="text" data-ng-model="model" data-dir="" />
      
      {{model}}
      <hr />
      <h3>console <button data-ng-click="$root.logs = []">clear console</button></h3>
      <ul>
        <li data-ng-repeat="log in $root.logs track by $index" data-ng-bind="log"></li>
      </ul>
    </div>

2 个答案:

答案 0 :(得分:2)

ng-model $viewChangeListener

的外部变更指令

使用.directive('extChange', function(){ return { require: 'ngModel', link: function(scope, element, attrs, modelCtrl) { var lastUserInput = modelCtrl.$viewValue; modelCtrl.$viewChangeListeners.push(function() { lastUserInput = modelCtrl.$viewValue; }); scope.$watch(attrs.ngModel, function watchHandler (value) { if (value!==lastUserInput) { scope.$eval(attrs.extChange, {$value:value}); } }); } } }); 保存最后一个用户输入,并让监视处理程序对此进行比较,以区分模型的外部更改与模型的用户输入更改。

ext-change

示例指令保存最后一个用户输入。当监视处理程序获取不同的值时,它将调用$value属性定义的Angular表达式。更改的值显示为<input ng-model="someInput" ng-change="userInput=someInput" ext-change="extInput=$value">

ext-change

ng-model指令与ng-change指令一起使用,并补充ext-change指令。

在此示例中,extInput指令仅更新模型外部更改的ng-change变量。 userInput指令仅更新用户更改的<input ng-model="someInput" ng-change="userEvent(someInput)" ext-change="externalEvent($value)"> 变量。

DEMO on JSFiddle

该指令也可用于调用函数。

{{1}}

答案 1 :(得分:1)

请勿使用$watch。你不应该使用它,你不得使用它,如果你使用$watch就会遇到麻烦,你已经遇到麻烦了,不要使用它。

使用控制流和事件。有可能你已经有很多观察者和范围汤,现在还不算太晚,尽快重构,这是你最好的。

&#13;
&#13;
angular.module('app', [])
  .controller('ctrl', function($scope) {

  })
  .directive('dir', function($rootScope) {
    return {
      require: 'ngModel',
      link: function($scope, element, attrs) {
        $rootScope.logs = [];

        $scope.modelChange = function(reason) {
          $rootScope.logs.push(reason);
        };

        $scope.modelChangedFromInput = function(model) {
          $scope.modelChange('From input');
        };

        $scope.buttonClick = function() {
          $scope.model = 'asd';
          $scope.modelChange('From button');
        };
      }
    }
  });
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div data-ng-app="app" data-ng-controller="ctrl">

  <input type="text" data-ng-model="model" data-dir="" data-ng-change="modelChangedFromInput()" />

  <button data-ng-click="buttonClick()">Set "model" to different value</button>

  {{model}}
  <hr />
  <h3>console <button data-ng-click="$root.logs = []">clear console</button>
  </h3>
  <ul>
    <li data-ng-repeat="log in $root.logs track by $index" data-ng-bind="log"></li>
  </ul>
</div>
&#13;
&#13;
&#13;