自己写的angularJs排序指令【原创】
首先,给大家看看指令完成的效果。(请注意区分下面几张图片中,对象值的变化)
好了,效果图已经看完了,如果大家有兴趣的话可以继续往下看,接下来要讲的是关于angularJs中filter内置好的order功能,如果熟悉这个功能的同学们可以跳过下面要讲的内容
orderBy这个功能其实是内置的过滤器,他可以在html和js代码中使用
html:{{ orderBy_expression | orderBy : expression : reverse}}
js :$filter('orderBy')(array, expression, reverse)
在这里我们只看html标签的运用,可以看出来他需要传入三个值
1.orderBy_expression :你需要排序的数组
2.expression :你需要根据哪个条件排序
3.reverse :正序还是倒序(boolean)
看到这里可能有的同学就知道为什么我要创建效果图中的这样的{"orderPredicate":"price","orderReverse":false}对象了。
由于这里不是详细讲过滤的所以想深入理解的话 登录官方的API吧 : http://docs.angularjs.cn/api/ng/filter/orderBy
现在开始进入主要内容了,首先我们要讲的是指令,不废话先上代码在分析
js:
angular.module('MyApp',[]) .controller('MyCtrl',function(){ var vm = this; //排序条件的数组 vm.orderList = [{ "title" : "价格", "value" : "price" },{ "title" : "数量", "value" : "count" }] //排序条件对象 vm.orderInfo = { orderPredicate : "",//排序的值 orderReverse : false//正反序 } }) .directive('orderList', function() { return { controller: function($scope, $element, $attrs, $transclude) { var lists = [];//排序条件的列表 this.getOpened = function(selectedItem) { //控制只能点击一个排序条件 angular.forEach(lists, function(item, key) { if (selectedItem != item) { item.showMe = false; } }); } //提供方法,在item生成的时候,将值放入lists中 this.addItem = function(item) { lists.push(item); } }, restrict: 'AE', template: '<ul class="list-group" ng-transclude></ul>', replace: true, transclude: true, link: function($scope, iElm, iAttrs, controller) {} }; }) .directive('orderListItem', function() { return { scope: { orderVaule: '=',//即将排序数组中的排序条件 orderReverse: '=',//排序条件的值 orderPredicate: '=',//控制排序的正序或倒序 iconUp: '@',//升序图标 iconDown: '@',//降序图标 }, controller: function($scope, $element, $attrs, $transclude) {}, require: '?^orderList',//'^'判断是否存在父容器oederList,'?'可以避免orderList不存在的时候不报错 restrict: 'AE', template: '<li class="list-group-item" ng-click="toogle(orderVaule)">' + '<span ng-transclude></span>' + '<i ng-show="showMe" class="glyphicon pull-right" ng-class="{true:\'{{iconUp}}\',false:\'{{iconDown}}\'}[orderReverse]"></i>' + '</li>', transclude: true, link: function($scope, iElm, iAttrs, controller) { //item渲染刚开始所有的图标都不显示 $scope.showMe = false; //讲渲染的item加入父容器的lists中 controller.addItem($scope); //点击item事件 $scope.toogle = function(value) { //正反序切换 $scope.orderReverse = !$scope.orderReverse; //将值赋予排序条件 $scope.orderPredicate = value; //并显示图标 $scope.showMe = true; //关闭其他item的图标 controller.getOpened($scope); } } }; })
html:
<body ng-controller="MyCtrl as vm"> <order-list> <order-list-item ng-repeat="item in vm.orderList" icon-up="glyphicon-arrow-up" icon-down="glyphicon-arrow-down" order-vaule="item.value" order-reverse="vm.orderInfo.orderReverse" order-predicate="vm.orderInfo.orderPredicate"> {{item.title}} </order-list-item> </order-list> {{vm.orderInfo}} </body>
可能有些同学疑惑 ng-controller="MyCtrl as vm" 这是什么意思,其实这是angularJs推荐的写法,为了避免与$scope的原型继承搞混。毕竟全部都是$scope也不太美观,实际上是这样的 var vm =$scope.vm = {}
大部分的讲解都在注释上了,如果有问题的可以在下方提问;另外这里的图标是不支持图片的,只支持图标,需要引入bootstrap.css和里面的图标功能。