自定义过滤器
创建 phonecatFilters 模块,用此模块注册自定义过滤器:
1 2 3 4 5
| angular.module('phonecatFilters', []).filter('checkmark', function() { return function(input) { return input ? '\u2713' : '\u2718'; }; });
|
过滤器的名字是“checkmark”,根据 input 判断 true 或 false,我们用 unicode 字符代替 true 或 false(\u2713 和 \u2718)。
我们需要给 phonecat 模块注册 phonecatFilters 模块。
1
| angular.module('phonecat', ['phonecatFilters']).
|
模板
我们需要引入 app/js/filters.js 文件
1 2
| <script src="js/controllers.js"></script> <script src="js/filters.js"></script>
|
Angular 模版使用过滤器的语法如下:
{{ expression | filter }}
我们在手机详情模版使用此过滤器:
1 2 3 4 5 6
| <dl> <dt>Infrared</dt> <dd>{{phone.connectivity.infrared | checkmark}}</dd> <dt>GPS</dt> <dd>{{phone.connectivity.gps | checkmark}}</dd> </dl>
|
实验
- 我们实验下 Angular 内建过滤器,在 index.html 添加以下绑定:
{{ “lower cap string” | uppercase }}
{{ {foo: “bar”, baz: 23} | json }}
{{ 1304375948024 | date }}
{{ 1304375948024 | date:”MM/dd/yyyy @ h:mma” }}
- 我们也可以创建带有输入元素的模型,把过滤器绑定和它联合起来。index.html 加以下代码试试:
1
| <input ng-model="userInput"> Uppercased: {{ userInput | uppercase }}
|
事件处理
在手机详情页加个点击缩缩图切换对应大图的效果。
控制器
1 2 3 4 5 6 7 8 9 10 11 12
| function PhoneDetailCtrl($scope, $routeParams, $http) { $http.get('phones/' + $routeParams.phoneId + '.json').success(function(data) { $scope.phone = data; $scope.mainImageUrl = data.images[0]; }); $scope.setImage = function(imageUrl) { $scope.mainImageUrl = imageUrl; } }
|
PhoneDetailCtrl 控制器,创建了 mainImageUrl 模型属性,默认值设为第一个手机图片的 URL。
我们也创建了 setImage 事件处理器,它将改变 mainImageUrl 的值。
模版
1 2 3 4 5 6 7
| <img ng-src="\{\{mainImageUrl}}" class="phone"> <ul class="phone-thumbs"> <li ng-repeat="img in phone.images"> <img ng-src="\{\{img}}" ng-click="setImage(img)"> </li> </ul>
|
我们给大图绑定 ngSrc 指令,设为 mainImageUrl 属性,也给缩略图注册了 ngClick 事件。当点击缩略图时,setImage 事件处理器会把 mainImageUrl 属性的值改成缩略图的 URL 。
实验
让我们往 PhoneDetailCtrl 添加一个新的控制器方法:
1 2 3
| $scope.hello = function(name) { alert('Hello ' + (name || 'world') + '!'); }
|
然后往 phone-details.html 模版添加以下代码:
1
| <button ng-click="hello('Elmo')">Hello</button>
|
REST 和自定义服务
最后为应用定义一个基于 REST 客户端的自定义服务,用此客户端我们可以更容易的发起 XHR 请求获取数据,不必使用底层的 $http API,HTTP 方法和 URL。
模版
自定义服务定义到 app/js/services.js 中,我们把它引入到布局模版中。此外,需要加载 angular-resource.js 文件,此文件的 $resource 服务包含 ngResource 模块,我们马上要用:
1 2
| <script src="js/services.js"></script> <script src="lib/angular/angular-resource.js"></script>
|
服务
1 2 3 4 5 6
| angular.module('phonecatServices', ['ngResource']). factory('Phone', function($resource){ return $resource('phones/:phoneId.json', {}, { query: {method:'GET', params:{phoneId:'phones'}, isArray:true} }); });
|
我们使用模块 API 注册自定义服务,用到了 factory(工厂) 函数。把 ‘Phone’ 服务名传到工厂函数里,工厂函数很像控制器的构造函数,都可以通过函数参数声明依赖。Phone 服务依赖于 $resource 服务。
$resource 服务几行代码就能创建一个 REST 客户端,此客户端可以取代底层的 $http 服务。
1
| angular.module('phonecat', ['phonecatFilters', 'phonecatServices']).
|
我们需要给 ‘phonecat’ 应用添加数组形式的 ‘phonecatServices’。
控制器
我们简化了子控制器(PhoneListCtrl 和 PhoneDetailCtrl),用新的服务 Phone 取代底层的 $http 服务。
Angular 的 $resource 服务比 $http 更易用,代码也更容易理解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function PhoneListCtrl($scope, Phone) { $scope.phones = Phone.query(); $scope.orderProp = 'age'; } function PhoneDetailCtrl($scope, $routeParams, Phone) { $scope.phone = Phone.get({phoneId: $routeParams.phoneId}, function(phone) { $scope.mainImageUrl = phone.images[0]; }); $scope.setImage = function(imageUrl) { $scope.mainImageUrl = imageUrl; } }
|
注意我们把:
1 2 3
| $http.get('phones/phones.json').success(function(data) { $scope.phones = data; });
|
换成了:
1
| $scope.phones = Phone.query();
|
非常值得注意的是,当调用 Phone 服务时, 我们没有传递回调函数。
结语
我们的应用完成啦,git checkout
命令可以跳回原先的步骤。
开发者指南 有更多的例子和详细资料。
更多代码实例,看 Cookbook 。
当你准备用 Angular 开发项目时,推荐你使用 angular 种子 引导开发。