博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通过angularjs的directive以及service来实现的列表页加载排序分页(转)
阅读量:6895 次
发布时间:2019-06-27

本文共 9557 字,大约阅读时间需要 31 分钟。

前两篇:(,)分别介绍了我们是如何做后端业务系统数据展示类的列表页以及动态搜索的,那么还剩下最重要的一项:数据展示。数据展示一般包含三部分:

  • 数据列头
  • 数据行
  • 分页统计信息,分页导航

技术依赖项:基于angularjs的MVVM模式,后台是spring mvc。

数据表格需求:

  • 需要支持列头的排序
  • 需要支持单页操作,局部更新(angular model更新),比如更新某行数据成功后,自动更新当前行的数据,而不需要刷新页面或者另外请求后台数据。
  • 需要支持数据逻辑运算以及复杂的html格式的数据,比如根据不同的数据值展示不同的按钮,文本等,展示的文本需要经过特定的逻辑运算等。
  • 需要有统计信息以及分页展示

第三方的组件:

  • jquery.datatable http://www.datatables.net/

最终展示的结果是html table,优点是支持嵌套表格等复杂功能,缺点是加载的文件大,且不能满足上面的需求angular model更新,对于复杂数据展示控制起来也比较复杂,需要额外的js编码工作。

  • angular ui-grid https://github.com/angular-ui/ui-grid/wiki/Getting-started

最终展示的结果是div,与angularjs兼容性很好,能支持表格在线编辑,缺点同样也是不能满足上面的需求angular model更新,对于复杂数据展示控制起来也比较复杂,需要额外的js编码工作。

第三方组件的特点就是功能多,但有些看起来很高级的功能我们基本上都不用,比如在线表格数据的编辑,嵌套表格等。我们必须的功能只有这些:排序,数据展示,分页,如果能支持angular model更新更好。所以我决定结合html table,angularjs来完成上面的需求。
数据加载:

由于我们的数据动态查询方案的存在,决定了大部分页面前后台交互的模式是相同的,所以采用angular service来提供一个listService供列表页使用。主要是分页大小的选择框,以及定义了一些可配置的参数,比如执行查询的请求地址,由于我们的动态查询以表单提交,所以是将整个表单参数序列化之后再加上分页相关信息然后提交到后端查询。

复制代码
angular.module('app.service', ['app.constant'])    .service('$listService', function () {        var $scopeLocal = {};        var pageSizeList = [{            "text": "10",            "value": "10"        }, {            "text": "20",            "value": "20"        }];        var defaultOptions = {            beforeSend: function () {            },            callback: function ($scope, data) {            },            error: function () {            },            pageSize: pageSizeList[0].value,            searchFormId: "searchForm",        };        this.init = function ($scope, option) {            var options = $.extend({}, defaultOptions, option);            $scopeLocal = $scope;            $scopeLocal.pageSizeList = pageSizeList;            $scopeLocal.pageRequest = {                "pageNum": 1, "pageSize": options.pageSize            };            $scopeLocal.pageRequest.getResponse = function (orderBy) {                var requestData = $("#" + options.searchFormId + "").serialize();                var url = options.listUrl + "?" + requestData + "&pageNum=" + $scopeLocal.pageRequest.pageNum + "&pageSize=" + $scopeLocal.pageRequest.pageSize;                if(angular.isDefined($scopeLocal.pageRequest.orderBy)&&$scopeLocal.pageRequest.orderBy!=""){                    url+="&orderBy="+$scopeLocal.pageRequest.orderBy;                }                $.ajax({                    type: "POST",                    url: url,                    dataType: 'json',                    async: false,                    beforeSend: options.beforeSend,                    error: options.error,                    success: function (data) {                        $scopeLocal.pageResponse = data;                        $scopeLocal.content = data.list;                        options.callback($scopeLocal, data);                    }                });            };         this.get = function () {                $scopeLocal.pageRequest.getResponse();            };        };    })
复制代码

使用时,只需要注入listService,然后配置上参数即可:

复制代码
mainApp.controller('manageCtrl', function ($scope, $http, $listService) {            var options = {                    listUrl:"
" }; $listService.init($scope, options); $listService.get(); });
复制代码

数据排序:
列头排序的方案是在列头上增加排序字段,通过angular directive来实现。排序的图片以及变换的样式是从jquery.datatable借鉴过来,逻辑并不复杂,无非就是显示排序标签以及根据用户的点击变换排序图标。

复制代码
angular.module('app.directives', []).directive("sortName", [ function() {    return {        restict : "A",        link : function(scope, element, attrs) {            var sortName = attrs["sortName"];            var sortType = attrs["sortType"];            if (!angular.isString(sortName) || sortName == "")                return;            if (!angular.isString(sortType) || sortType == "") {                element.removeClass("sorting").removeClass("sorting_asc").removeClass("sorting_desc").addClass("sorting").attr("sort-type","asc");            }            $(element).bind("click", function(){                var thisObj=$(this);                var sortType = thisObj.attr("sort-type");                if (!angular.isString(sortName) || sortName == "")                    return;                if (!angular.isString(sortType) || sortType == "")                    return;                var orderBy = sortName + " " + sortType;                scope.pageRequest.orderBy=orderBy;                scope.pageRequest.getResponse();                if (sortType == "asc") {                    thisObj.removeClass("sorting").removeClass("sorting_asc").removeClass("sorting_desc").addClass("sorting_asc").attr("sort-type","desc");                } else if (sortType == "desc") {                    thisObj.removeClass("sorting").removeClass("sorting_asc").removeClass("sorting_desc").addClass("sorting_desc").attr("sort-type","asc");                }                thisObj.siblings().each(function (){                    var item=$(this);                    if(typeof(item.attr("sort-name"))!="undefined"){                        item.removeClass("sorting").removeClass("sorting_asc").removeClass("sorting_desc").addClass("sorting");                    }                });                scope.$apply();            });        }    }} ]);
复制代码

一个scope作用域的问题,在directive中获得的scope比较特殊,它的值变更不会影响外层页面上的$scope。因为我们需要在用户点击排序按钮后进行数据更新,所以我们需要调用$apply方法将scope的变化传播出去。

html中只需要在列头指定排序字段即可实现排序功能:sort-name,值是需要排序的字段:

编号名称

数据展示:
直接在页面中采用table来布局,数据行采用angularjs来做加载。table布局的优点在于:直观上很清晰,处理某些特殊数据行时也比较容易,重要的是能够很容易的支持angular model 更新。

复制代码
编号 名称 状态 描述 操作
启用
禁用
编辑 启用 禁用
复制代码

分页信息:

采用angularjs ui自带的uib-pagination。由于需要支持当前页记录大小的选择,如果每个页面都需要包含分页相关内容,这样代码会比较冗余,于时很容易的我们可以借助angular directive来解决:

复制代码
angular.module('app.directives', []).directive("pagerFooter", [ function() {    return {        restrict : "A",        link : function(scope, element) {            return null;        },        templateUrl : "../app/template/pagerFooter.html"    }} ])
复制代码
复制代码
每页
{
{$select.selected.text}}
条记录 总共条记录
复制代码

使用时,我们只需要这样指定:加一个pager-footer的属性。

 

写这个指令时遇到一个编码问题,模板页中出现的中文,在spring mvc环境下调用中乱码,最终在web.xml中增加配置得以解决:

html
text/html;charset=utf-8

目前还有一个疑问没有得到解决,就是模板页中必须还要指定<meta charset="UTF-8">,否则也会显示成乱码,回头找时间整体研究下spring mvc下的编码。

数据行数据的model更新

以避免通过二次请求或者刷新页面来重新加载数据。比如行数据中有状态一栏,操作列会根据状态值动态显示启用或者停用按钮,当用户点击启用按钮操作成功后,当前数据行的状态栏数据需要动态更新,且不需要请求后台也不需要刷新页面,我们可以非常容易的通用ng-bind来让其自动更新:

操作列绑定事件:

操作成功后更新model,页面数据自动更新。

复制代码
$scope.enabled=function(theme)            {                bootbox.confirm("确认操作吗?", function (flag) {                    if (flag) {                        var status=theme.status==1?0:1;                        var model={id:theme.id,status:status};                        $http.post("
",model).success(function(ret){ if (ret.err) { bootbox.alert(ret.err); } else { theme.status=status; bootbox.alert("操作成功!"); } }); } }); };
复制代码

列表页最终效果

 

上述的功能虽然不能解决所有场景的问题(嵌套表格,在线编辑表格,换肤等),但常见的业务操作均能满足,足够简单,不需要依赖第三方组件,重要的是能够完成其它js组件所不擅长的model更新场景以及复杂列的运算以及控制。我目前还在寻找其它的组件,如果有即能满足上述的需求又使用简单那么也是可以替换的,但做为学习总结总结倒也不错。

 

http://www.cnblogs.com/ASPNET2008/p/5311979.html

 

转载于:https://www.cnblogs.com/softidea/p/5312833.html

你可能感兴趣的文章
解决iOS上传包报错ERROR ITMS-90168
查看>>
抽象类和接口的区别
查看>>
关于#define你知道多少?
查看>>
Linux Iptables 双网卡实现网关路由及内网web mail ftp服务映射
查看>>
MySQL存储过程(1)定义
查看>>
使得CI在NetBeans 8.0中自动提示CI相关类和方法
查看>>
表单enctype 与 php处理
查看>>
《MS SQL Server 2000管理员手册》系列——36. 解决常见的效能问题
查看>>
对不同部门设置不同的共享盘符
查看>>
tcp有限状态机分析
查看>>
工作组和域
查看>>
Linux内核线程
查看>>
yarn和cnpm 配置
查看>>
第四题小案例3
查看>>
设计模式-策略模式
查看>>
Ubuntu 下Rsync配置及使用
查看>>
ipad开发需要投入更多的精力
查看>>
Linux服务器性能评估与优化
查看>>
C#往文件中追加文本内容信息
查看>>
让Openwrt在U盘运行
查看>>