【问题标题】:Making Angular Filter Dynamic in the controller在控制器中使角度过滤器动态化
【发布时间】:2016-08-07 21:29:27
【问题描述】:

我看到了一些其他帖子,我认为这些帖子可能会有所帮助,但没有任何运气。当我静态指定要过滤的属性时,我有一个可以正常工作的过滤器。我正在构建一个角度组件,我不知道哪些数据将实际传递到组件中。例如,这里有一些示例数据:

this.customers = [
  { name: 'Jim', city: 'Minneapolis', state: 'MN', zip: 44332 },
  { name: 'Boe', city: 'Scottsdale', state: 'AZ', zip: 44332 },
  { name: 'Tom', city: 'S.F.', state: 'CA', zip: 11223 },
  { name: 'Joe', city: 'Dallas', state: 'TX', zip: 34543 },
  { name: 'Jon', city: 'L.A.', state: 'CA', zip: 56433 }
];

我的静态过滤器效果很好:

public filterTextChangeLocal($event: ng.IAngularEvent) {
  if (this.itemDisplayProperty = "name") {
    this.filteredItems = this.$filter("filter")(this.items, {name: this.ngModelValue});
  } else if (this.itemDisplayProperty = "city") {
    this.filteredItems = this.$filter("filter")(this.items, {city: this.ngModelValue});
  } else if (this.itemDisplayProperty = "state") { 
    this.filteredItems = this.$filter("filter")(this.items, {state: this.ngModelValue});
  } else if (this.itemDisplayProperty === "zip") {
    this.filteredItems = this.$filter("filter")(this.items, {zip: this.ngModelValue});
  }
}

问题是组件的用户可以传入任何类型的数据,其属性可能完全不同,所以我需要一些可以解释任何指定属性的东西。我有一个名为“itemDisplayProperty”的隔离范围属性,它允许用户从他们的数据中指定他们想要在下拉列表中显示的属性,这就是我需要过滤的属性。他们可以说,“item-display-property="address",地址属性中的数据将显示在下拉列表中。我试过了,但由于不允许使用多个“this”字样,所以不起作用:

this.filteredItems = this.$filter("filter")(this.items, {
  this.itemDisplayProperty : this.ngModelValue
});

这是我的输入和下拉列表供参考:

<input type="text" class="form-control" 
       ng-change="ctrl.filterTextChangeLocal($event)" 
       ng-model="ctrl.ngModelValue" 
       ng-click="ctrl.openDropdown($event)" />

<ul class="dropdown-menu list-group" ng-if="!ctrl.ngDisabled">
  <li class="list-group-item" 
      ng-repeat="row in ctrl.filteredItems" 
      ng-mousedown="ctrl.onSelectedLocal(row, $event)">

    {{row[ctrl.itemDisplayProperty]}}
  </li>
</ul>

【问题讨论】:

    标签: javascript angularjs filter angularjs-ng-repeat angular-ngmodel


    【解决方案1】:

    为了重构filterTextChangeLocal 中的静态过滤器,您只需构造一个带有动态键的$filter 表达式。

    这可以通过使用所谓的bracket notation来实现:

    var obj = {};
    obj[myKey] = value;
    

    重构后的filterTextChangeLocal 看起来像这样:

    public filterTextChangeLocal($event: ng.IAngularEvent) {
        var filterExpression = {};
        filterExpression[this.itemDisplayProperty] = this.ngModelValue;
    
        this.filteredItems = this.$filter("filter")(this.items, filterExpression);
    }
    

    【讨论】:

    • 感谢 Cosmin,在刷新并查看您的帖子之前,我已经为自己的问题添加了答案。这基本上是相同的想法,并且效果也很好。我会标记为答案。谢谢你的时间。
    • 我将它添加到我的项目中并且它工作正常......谢谢:)
    【解决方案2】:

    我以这种方式解决了我自己的问题,这似乎是一种在对象内使用变量的新 ES6 方式。标记的答案也可以:

     this.filteredItems = this.$filter("filter")(this.items, {[this.itemDisplayProperty] : this.ngModelValue});
    

    【讨论】:

      【解决方案3】:

      好的,没错,在 ES6 中你可以使用计算的比例。

      使用 ES5,您可以创建一个像这样的过滤器对象(在您的控制器中使用 var self=this;):

      var filterObj = {};
      filterObj[self.itemDisplayProperty] = self.ngModelValue;
      self.filteredItems = $filter("filter")(self.items, filterObj);
      

      请看下面的演示或jsfiddle。

      只是对变量名称的注释。避免在您的名称中使用 ng 前缀(例如,在您的代码中使用 ngDisabled)。因为这个变量与 AngularJs 无关,不同的名字会让你的代码更具可读性。像showDrop 这样的东西会更好。

      angular.module('demoApp', [])
      	.controller('mainController', MainController)
          .directive('dynFilter', DynFilterDirective);
          
      function DynFilterDirective($filter) {
      	return {
          	restrict: 'E',
              controllerAs: 'ctrl',
              templateUrl: 'components/dynFilterTempl.html',
              bindToController: {
              	items: '=',
              	itemDisplayProperty: '='
              },
              scope: {},
              controller: function() {
              	var self = this;
                  self.filterTextChangeLocal = function($event) {
                    	var filterObj = {};
                    	filterObj[self.itemDisplayProperty] = self.ngModelValue;
                    	console.log(filterObj);
                      self.filteredItems = $filter("filter")(self.items, filterObj);
                	};
              }
          }
      }
      function MainController($filter) {
      	var vm = this;
          vm.items = [
                  { name: 'Jim', city: 'Minneapolis', state: 'MN', zip: 44332 },
                  { name: 'Boe', city: 'Scottsdale', state: 'AZ', zip: 44332 },
                  { name: 'Tom', city: 'S.F.', state: 'CA', zip: 11223 },
                  { name: 'Joe', city: 'Dallas', state: 'TX', zip: 34543 },
                  { name: 'Jon', city: 'L.A.', state: 'CA', zip: 56433 },
              ];
      	vm.keys = Object.keys(vm.items[0]);
          vm.curProp = vm.keys[0];
      }
      <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.4/angular.js"></script>
      <div ng-app="demoApp" ng-controller="mainController as mainCtrl">
          {{Object.keys(mainCtrl.items[0])}}
          Choose your filter: <select ng-options="prop for prop in mainCtrl.keys" ng-model="mainCtrl.curProp"></select>
          <dyn-filter item-display-property="mainCtrl.curProp" items="mainCtrl.items"></dyn-filter>
      
      <script type="text/ng-template" id="components/dynFilterTempl.html">
       <input type="text" class="form-control" ng-change="ctrl.filterTextChangeLocal($event)"
          ng-model="ctrl.ngModelValue" ng-focus="ctrl.showDrop = true" ng-blur="ctrl.showDrop = false" />
      
      <ul class="dropdown-menu list-group" ng-show="ctrl.showDrop">
          <li class="list-group-item" ng-repeat="row in ctrl.filteredItems" 
          ng-mousedown="ctrl.onSelectedLocal(row, $event)">
              {{row[ctrl.itemDisplayProperty]}}
          </li>
      </ul>
      </script>
      </div>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-12
        • 2015-08-17
        • 1970-01-01
        • 2017-04-04
        • 1970-01-01
        • 2016-01-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多