使Angular Filter在控制器中动态化

时间:2016-04-15 19:08:20

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

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

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 ="地址&#34 ;,地址属性中的数据将显示在下拉列表中。我尝试了这个,但并没有像多个人那样工作,而且#34;不允许使用单词:

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>

3 个答案:

答案 0 :(得分:3)

为了重构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);
}

答案 1 :(得分:1)

我用这种方式解决了我自己的问题,似乎是一种在对象中使用变量的新ES6方式。明确的答案也会起作用:

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

答案 2 :(得分:0)

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

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

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

请查看下面的演示或此jsfiddle

只记下您的变量名称。避免在您的名字中使用ng前缀(例如代码中的ngDisabled)。因为此变量与AngularJs无关,而另一个名称将使您的代码更具可读性。像showDrop这样的东西会更好。

&#13;
&#13;
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];
}
&#13;
<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>
&#13;
&#13;
&#13;