过滤器在数据从作用域传递到指令上时进行转换,但并不改变源数据,这允许在视图中显示时能够灵活地格式化或者转换数据。
AngularJS具有两种类型的内置过滤器:一类是对单个数据进行操作的,另一类是对数据集合进行操作的。
一、过滤单个数据的值
用于单个数据的内置过滤器
currency 对货币值进行格式化,在过滤器名之后添加冒号:,然后添加一个字符串表示想替换成的符号,比如英镑符号。
date 对日期值进行格式化,这个日期可以是字符串,js日期对象或者毫秒数等等。使用这个过滤器时,需要指定过滤器名date,之后跟一个冒号,再然后是一个格式化字符串,由要显示的各个日期成分组成。如data|date:"dd MMM yy"或者 data|date:"shortDate".shortDate是date过滤器的格式字符串,这是date过滤器所支持的常用日期表达式的几个快捷格式之一。快捷格式字符串表见P340.
json 从JS对象创建json字符串,例如data|json。
number 对数字值进行格式化,调整小数位数,根据需要进行四舍五入。应用这个过滤器时,只需使用竖线符号和过滤器名,然后是一个冒号和要显示的小数位数,number过滤器会自动在千分位处插入逗号。data|number:2 保留两位小数
uppercase/lowercase 将字符串格式化为全部大写或者全部小写,例如data|uppercase.
本地化过滤器输出
currency、number和date过滤器都支持使用本地化规则对数据进行格式化,规则定义在本地化文件中。
二、过滤集合
2.1 限制项目数量limitTo
limitTo过滤器可以限制从一个数据对象构成的数组中取出的项目的数量,这在一个仅能容纳一定数量项目的页面中尤为有用。
limitTo过滤器配置为一个整数,例如data|limitTo:5,过滤器会从数组中选出最前5个对象。如果你选择一个负数,例如data|limitTo:-5,过滤器会从数组中选出最后五个对象。
如果你指定了一个大于数组大小的数值,LimitTo过滤器将会返回数组中所有对象。
2.2 选取项filter
filter过滤器用于从数组中选出一些对象。选取条件可以指定为一个表达式,或者一个用于匹配属性值的map对象,或者一个函数。
例如data|filter:{category:'Fish'},通过map对象进行选取,指定了想要选取的对象必须是category属性为fish的。
如果你通过一个函数过滤,选出的项目将会是那些使得函数执行结果返回true的。
$scope.selectItems=function(item){ return item.category=='Fish'||item.name=='Beer'; }
<tr ng-repeat="p in products|filter:selectItems"> </tr>
在本例中,定义了一个名为selectItems的作用域行为。这个行为将会依次调用集合中的每个项,并按照顺序返回每个对象。
2.3 对项目进行排序 orderBy
使用如下:<tr ng-repeat="p in products | orderBy:'price'"></tr> 这里price需要加引号,如果不加引号,orderBy会失败,会假设你想使用一个名为price的作用域变量或者控制器变量,并且认为你将会在某处着手定义这个变量。
1)设置排序方向
在只设定一个属性名的情况下,相当于隐式地请求过滤器为对象进行升序排列,可以通过显式地使用+或-字符来设置排序顺序。在属性名前加入一个负号前缀(-),就指定了应该按照降序排列对象,前缀指定为正号(+)或者不指定前缀,则具有升序排列的效果。
2)使用函数排序
之所以需要小心的将属性名指定为字符串的原因是因为orderBy过滤器也能够使用一个函数进行排序,也就是说允许不直接按照某个属性值的方式进行排序。用于排序的函数需传入一个数据数组中的对象,然后返回一个在排序时用于比较的对象或值。
<tr ng-repeat="p in products | orderBy:myCustomSorter"> <td>{{p.name}}</td> <td>{{p.category}}</td> <td>{{p.expiry}}</td> <td class="text-right">{{p.price | currency }}</td> </tr>
$scope.myCustomSorter = function (item) { return item.expiry < 5 ? 0 : item.price; }
这个函数的效果是,在升序排序下凡是具有较小expiry值的那些项将被放在数据数组的前端。
3)用多个谓语进行排序
可以配置orderBy过滤器为一个属性名或函数名构成的数组,用于依次进行排序。如果两个对象对于数组中的第一个属性或者函数具有相同的值,然后orderBy过滤器就会考虑使用第二个值或函数,依次继续下去直到能够对数据对象分出次序,或者尝试完所有的属性/函数。
<tr ng-repeat="p in products | orderBy:[myCustomSorter, '-price']"> <td>{{p.name}}</td> <td>{{p.category}}</td> <td>{{p.expiry}}</td> <td class="text-right">{{p.price | currency }}</td> </tr>
三、链式过滤器
过滤器通过竖线(|)符号链式连接在一起,并按照所写下的顺序执行计算。
<tr ng-repeat="p in products | orderBy:[myCustomSorter, '-price'] | limitTo: 5">
先执行orderBy,然后再执行limitTo
四、创建自定义过滤器
4.1 创建格式化数据值的过滤器
过滤器是由Module.filter方法创建的,该方法接收两个参数:待创建的过滤器名称和一个工厂函数。
angular.module("exampleApp") .filter("labelCase", function () { return function (value, reverse) { if (angular.isString(value)) { var intermediate = reverse ? value.toUpperCase() : value.toLowerCase(); return (reverse ? intermediate[0].toLowerCase() : intermediate[0].toUpperCase()) + intermediate.substr(1); } else { return value; } }; });
工人函数接收两个参数:第一个是待过滤的值(在应用过滤器时由AngularJS提供),第二个参数用于允许过滤器用途被颠倒过来,也就是首字母为小写而剩余其他字母为大写。
引入过滤器文件的script元素要放在定义模板的文件后面,因为js文件中的代码依赖于已经被定义的这个模板。
<tr ng-repeat="p in products | orderBy:[myCustomSorter, '-price'] | limitTo: 5"> <td>{{p.name | labelCase }}</td> <td>{{p.category | labelCase:true }}</td> <td>{{p.expiry}}</td> <td class="text-right">{{p.price | currency }}</td> </tr>
4.2 创建一个集合过滤器
.filter("skip", function () { return function (data, count) { if (angular.isArray(data) && angular.isNumber(count)) { if (count > data.length || count < 1) { return data; } else { return data.slice(count); } } else { return data; } } });
<tr ng-repeat="p in products | skip:2 | limitTo: 5"> <td>{{p.name}}</td> <td>{{p.category}}</td> <td>{{p.expiry}}</td> <td class="text-right">{{p.price | currency }}</td> </tr>
这里传给skip过滤器的data的是整个数组对象,而不是数组中的某一个对象。
4.3 在已有的过滤器上搭建新的过滤器
.filter("take", function ($filter) { return function (data, skipCount, takeCount) { var skippedData = $filter("skip")(data, skipCount); return $filter("limitTo")(skippedData, takeCount); } });
<tr ng-repeat="p in products | take:2:5"> <td>{{p.name}}</td> <td>{{p.category}}</td> <td>{{p.expiry}}</td> <td class="text-right">{{p.price | currency }}</td> </tr>
这是第一次使用一个worker函数需要多于一个配置参数的过滤器,可以看到为这些参数提供值时使用冒号将他们进行分割的。