【问题标题】:watchcollection swallowing an attribute being watchedwatchcollection 吞下被监视的属性
【发布时间】:2015-06-27 11:41:14
【问题描述】:

有两个属性selCountrysearchText。有一个监视这两个变量的手表。第一个绑定到一个选择元素,另一个是一个输入文本字段。

我期望的行为是:如果我更改下拉值,文本框应该清除,反之亦然。但是,由于我编写手表的方式,第一次按键(与选择元素交互后)会吞下按键。

必须有某种角度的方式告诉 Angular 不要处理发生在这些变量上的变量变化;仍然允许他们的更改传播到视图...?

  $scope.$watchCollection('[selCountry, searchText]', function(newValues, oldValues, scope){
    console.log(newValues, oldValues, scope.selCountry, scope.searchText);
    var newVal;
    if(newValues[0] !== oldValues[0]) {
      console.log('1');
      newVal = newValues[0];
      scope.searchText = '';
    }
    else if(newValues[1] !== oldValues[1]) {
      console.log('2');
      newVal = newValues[1];
      scope.selCountry = '';
    }
    $scope.search = newVal;
    var count = 0;
    if(records)
      records.forEach(function(o){
        if(o.Country.toLowerCase().indexOf(newVal.toLowerCase())) count++;
      });
    $scope.matches = count;
  });

Plunk

【问题讨论】:

    标签: javascript angularjs angularjs-watch


    【解决方案1】:

    我认为您遇到的问题是您正确捕获了监视事件,但是当您更改第二个变量的值时,它也会被 watchCollection 处理程序捕获并清除该值。例如:

    selCountry = 'Mexico'
    

    然后你改变

    selText = 'City'
    

    代码如您所愿捕获 selText 更改。它继续清除 selCountry。但是由于您更改了作用域对象上 selCountry 的值,这样做也会调用 watchCollection,然后它会说“好的,我现在需要清除 searchText”。

    您应该能够通过使用 ng-change 指令的 onChange 事件处理程序捕获更改来解决此问题。试试下面的

    // Comment out/remove current watchCollection handler.
    // Add the following in JS file
      $scope.searchTextChange = function(){
        $scope.selCountry = '';
        $scope.search = $scope.searchText;
        search($scope.search);
      };
      $scope.selectCountryChange = function(){
        $scope.searchText = '';
        $scope.search = $scope.selCountry;
        search($scope.search);
      };
    
      function search(value){
        var count = 0;
        if(records)
          records.forEach(function(o){
            if(o.Country.toLowerCase().indexOf(value.toLowerCase())) count++;
          });
        $scope.matches = count;
      }
    

    在你的 HTML 文件中

    <!-- Add ng-change to each element as I have below -->
      <select ng-options="country for country in countries" ng-model="selCountry" ng-change="selectCountryChange()">
        <option value="">--select--</option>
      </select>
      <input type="text" ng-model="searchText" ng-change="searchTextChange()"/>
    

    新插件:http://plnkr.co/edit/xCWxSM3RxsfZiQBY76L6?p=preview

    【讨论】:

      【解决方案2】:

      我认为你太用力了,可以这么说。你可以用更少的复杂性和watches 来做。

      我建议您使用一些 3rd 方库,例如 lodash,使数组/对象操作更容易。试试这个 plunker http://plnkr.co/edit/YcYh8M,我认为它可以满足您的需求。

      每次选择 country 项目时,它都会清除 search text,但还会在输入内容时自动过滤 options 以匹配搜索文本。

      HTML 模板

      <div ng-controller="MainCtrl">
        <select ng-options="country for country in countries" 
                ng-model="selected" 
                ng-change="search = null; searched();">
          <option value="">--select--</option>
        </select>
        <input type="text" 
               placeholder="search here"
               ng-model="search" 
               ng-change="selected = null; searched();">
        <br>
        <p>
           searched: {{ search || 'null' }},
           matches : {{ search ? countries.length : 'null' }}
        </p>
      </div>
      

      JavaScript

      angular.module('myapp',[])
        .controller('MainCtrl', function($scope, $http) {
          $http.get('http://www.w3schools.com/angular/customers.php').then(function(response){
            $scope.allCountries = _.uniq(_.pluck(_.sortBy(response.data.records, 'Country'), 'Country'));
            $scope.countries = $scope.allCountries;
          });
      
          $scope.searched = function() {
            $scope.countries = $scope.allCountries;
      
            if ($scope.search) {
              var result = _.filter($scope.countries, function(country) {
                return country.toLowerCase().indexOf($scope.search.toLowerCase()) != -1;
              });            
              $scope.countries = result;
            }
          };
        });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-07
        • 2018-02-11
        • 2018-12-14
        • 2015-06-07
        • 1970-01-01
        相关资源
        最近更新 更多