与ng-change和select的交互 - 更改数据源触发器更改

时间:2015-09-16 18:39:08

标签: javascript angularjs

请检查这个plunkr:http://plnkr.co/edit/ke4Cjg3gnf2pWUKW1f2b?p=preview

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

app.controller('controller', ['$scope', '$timeout', function($scope, $timeout) {
    $scope.items = [
      {name:'candy'},
      {name:'chocolate'}
    ];
    $scope.choice = null;

    $scope.test = function() { 
      console.log( 'fired' );
    }
    
    $timeout( function(){
      $scope.choice = $scope.items[0];
    }, 2000);
    
    $timeout( function(){
      $scope.items = [
        {name:'hershey'},
        {name:'mint'}
      ];
    }, 5000);
}]);

    <select 
      ng-model="choice" 
      ng-options="item as item.name for item in items"
      ng-change="test()">
    </select>

我有一个使用ng-options和ng-change事件的选择框。 Ng-change文档声明如下:

  

仅当输入值的更改导致将新值提交给模型时,才会评估ngChange表达式。

     

不会评估:

     
      
  • 如果从$ parsers转换管道返回的值有   没有改变
  •   
  • 如果输入继续无效,因为模型将保持为空
  •   
  • 如果以编程方式更改模型,而不是通过更改输入值
  •   

显然,如果我以编程方式将模型设置为某物,则没有任何反应,但我发现当我动态更改ng-options的来源时,ng-change正在触发,除非 ng-model等于结果更改时的null值。

这是一个错误还是打算?如果打算,如果不首先将ng-model设置为null,如何在不导致ng-change的情况下更改ng-options的来源?如果没有,我会去报告这种奇怪的行为。

谢谢!

1 个答案:

答案 0 :(得分:2)

这里发生了什么:

  1. 您从下拉列表中选择一个值(例如糖果)。
  2. 超时后。在$ scope.items中创建一个新数组。此时,angularjs将使用一组新项重新填充HTML下拉框(选择)。这将导致DOM中的元素将其值从先前选择的(例如糖果)更改为null。
  3. 此更改会导致评估ng-change表达式。
  4. 这是有效的,因为a)存在更改(从candy到null)和b)更改不是通过对模型的编程更改(而是通过底层DOM元素)来完成的。

    解决方法取决于您想要做什么。在您提供的示例中,基础值将始终更改,因为新选项将替换所有旧选项。但请考虑以下示例,其中我选择删除巧克力并添加两个新值(保留糖果选项):

    $timeout( function(){
      delete $scope.items[1]; // removes item choclate from the list.
    
      // Add new items
      $scope.items[1] = {name : 'hershey' };
      $scope.items[2] = {name : 'mint' };
    
    }, 5000);
    

    在这种情况下,如果用户选择&#34; candy&#34;由于所选选项保持不变,因此不会触发ng-change。另一方面,如果用户选择&#34; chocolate&#34;,则更改将触发(因为值从&#34; chocolate&#34;变为null)。以下是您可能需要考虑的一些选项:

    1. 仅向下拉列表中添加项目。
    2. 如果需要删除所选选项,则将该值设置为null(由于您是以编程方式设置模型,因此不会触发)。
    3. 替换整个阵列,以便触发ng-change但在ng-change调用的函数内执行检查,以便处理模型未触发的情况。