Javascript watchcollection正在吞咽正在监视的属性

Javascript watchcollection正在吞咽正在监视的属性,javascript,angularjs,angularjs-watch,Javascript,Angularjs,Angularjs Watch,有两个属性selCountry和searchText。有一块手表监视这两个变量。第一个绑定到select元素,另一个是输入文本字段 我期望的行为是:如果我更改下拉值,textbox应该清除,反之亦然。然而,由于我编写手表的方式,第一次按键(与select元素交互后)会吞下按键 必须有某种角度的方法告诉angular不要处理发生在这些变量上的变量变化;但仍然允许他们的更改传播到视图 $scope.$watchCollection('[selCountry, searchText]', func

有两个属性
selCountry
searchText
。有一块手表监视这两个变量。第一个绑定到select元素,另一个是输入文本字段

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

必须有某种角度的方法告诉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;
  });

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

selCountry = 'Mexico'
然后你改变

selText = 'City'
这段代码捕获了您期望的selText更改。它继续清除出这个国家。但是由于您在scope对象上更改了selCountry的值,这样做也会调用watchCollection,它会说“好的,我现在需要清除searchText”

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

// 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()"/>

--挑选--

新的普朗克:

可以说,我认为你把它推得太用力了。您只需降低复杂性并观看
即可

我建议您使用一些第三方库,例如,使数组/对象操作更容易。试试这个,我想它能满足你的需求

每次选择
国家/地区
项目时,它都会清除
搜索文本
,但也会自动过滤
选项
,以便在键入内容时匹配搜索文本

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>
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;
      }
    };
  });