AngularJS中的Directive自定义一个表格

 更新时间:2016年1月26日 10:02  点击:2170

先给大家说下表格的需求:

● 表格结构

<table>
<thead>
<tr>
<th>Name</th>
<th>Street</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>></td>
<td>></td>
<td>></td>
</tr>
</tbody>
</table>
<div>4行</div>

● 点击某个th,就对该列进行排序
● 可以给表头取别名
● 可以设置某个列是否显示
● 表格下方有一行显示总行数

我们希望表格按如下方式展示:

<table-helper datasource="customers" clumnmap="[{name: 'Name'}, {street: 'Street'}, {age: 'Age'}, {url: 'URL', hidden: true}]"></table-helper>

以上,datasource的数据源来自controller中$scope.customers,大致是{name: 'David',street: '1234 Anywhere St.',age: 25,url: 'index.html'}这样的格式,具体略去。

columnmap负责给列取别名,并且决定是否显示某个列。

如何实现呢?

Directive大致是这样的:

var tableHelper = function(){
var template = '',
link = function(scope, element, attrs){
}
return {
restrict: 'E',
scope: {
columnmap: '=',
datasource: '='
},
link:link,
template:template
}; 
}
angular.module('directiveModule')
.directive('tableHelper', tableHelper); 

具体来说,

首先要监视datasource的变化,一旦有变化,就重新加载表格。

scope.$watchCollection('datasource', render);
//初始化表格
function render(){
if(scope.datasource && scope.datasource.length){
table += tableStart;
table += renderHeader();
table += renderRows() + tableEnd;
//加载统计行
renderTable();
}
} 

加载表格大致分成了三个步骤,加载表头,加载表格体,加载统计行。

//加载头部
function renderHeader(){
var tr = '<tr>';
for(var prop in scope.datasource[0]){
//{name: 'David',street: '1234 Anywhere St.',age: 25,url: 'index.html'}
//根据原始列名获取别名,并考虑了是否显示列的情况
var val = getColumnName(prop);
if(val){
//visibleProps存储的是原始列名
visibleProps.push(prop);
tr += '<th>' + val + '</th>';
}
}
tr += '</tr>';
tr = '<thead>' + tr '</thead>';
return tr;
}
//加载行
function renderRows(){
var rows = '';
for(var i = 0, len = scope.datasource.length; i < len; i++){
rows += '<tr>';
var row = scope.datasource[i];
for(var prop in row){
//当前遍历的原始列名是否在visibleProps集合中,该集合存储的是原始列名
if(visibleProps.indexOf(prop) > -1){
rows += '<td>' + row[prop] + '</td>';
}
}
rows += '</tr>';
}
rows = '<tbody>' + rows + '</tbody>';
return rows;
}
//加载统计行
function renderTable(){
table += '<br /><div class="rowCount">' + scope.datasource.length + '行</div>';
element.html(table);
table = '';
} 

加载表头的时候,用到了一个根据原始列名获取别名的方法。

//根据原始列名获取列的别名,并考虑是否隐藏列的情况
function getColumnName(prop){
if(!scope.columnmap) return prop;
//得到[{name: 'Name'}]
var val = filterColumnMap(prop);
if(val && val.length && !val[0].hidden) return val[0][prop];
else return null;
}

在getColumnName方法中,用到了一个根据原始列名

//比如根据name属性,这里得到[{name: 'Name'}]
//[{name: 'Name'}, {street: 'Street'}, {age: 'Age'}, {url: 'URL', hidden: true}]
function filterColumnMap(prop) {
var val = scope.columnmap.filter(function(map) {
if (map[prop]) {
return true;
}
return false;
});
return val;
}

具体代码如下:

(function(){
var tableHelper = fucntion(){
var template = '<div class="tableHelper"></div>',
link = function(scope, element, attrs){
var headerCols = [], //表头列们
tableStart = '<table>',
tableEnd = '</table>',
table = '',
visibleProps = [],//可见列
sortCol = null,//排序列
sortDir =1;
//监视集合
sscope.$watchCollection('datasource', render);
//给表头th绑定事件
wireEvents();
//初始化表格
function render(){
if(scope.datasource && scope.datasource.length){
table += tableStart;
table += renderHeader();
table += renderRows() + tableEnd;
//加载统计行
renderTable();
}
}
//给th添加click事件
function wireEvents()
{
element.on('click', function(event){
if(event.srcElement.nodeName === 'TH'){
//获取列的名称
var val = event.srcElement.innerHTML;
//根据列的别名获取原始列名
var col = (scope.columnmap) ? getRawColumnName(val) : val;
if(col){
//对该列进行排序
sort(col);
}
}
});
}
//给某列排序
function sort(col){
if(sortCol === col){
sortDir = sortDir * -1;
}
sortCol = col;
scope.datasource.sort(function(a,b){
if(a[col] > b[col]) return 1 * sortDir;
if(a[col] < b[col]) return -1 * sortDir;
return 0;
});
//重新加载表格
render();
}
//加载头部
function renderHeader(){
var tr = '<tr>';
for(var prop in scope.datasource[0]){
//{name: 'David',street: '1234 Anywhere St.',age: 25,url: 'index.html'}
//根据原始列名获取别名,并考虑了是否显示列的情况
var val = getColumnName(prop);
if(val){
//visibleProps存储的是原始列名
visibleProps.push(prop);
tr += '<th>' + val + '</th>';
}
}
tr += '</tr>';
tr = '<thead>' + tr '</thead>';
return tr;
}
//加载行
function renderRows(){
var rows = '';
for(var i = 0, len = scope.datasource.length; i < len; i++){
rows += '<tr>';
var row = scope.datasource[i];
for(var prop in row){
//当前遍历的原始列名是否在visibleProps集合中,该集合存储的是原始列名
if(visibleProps.indexOf(prop) > -1){
rows += '<td>' + row[prop] + '</td>';
}
}
rows += '</tr>';
}
rows = '<tbody>' + rows + '</tbody>';
return rows;
}
//加载统计行
function renderTable(){
table += '<br /><div class="rowCount">' + scope.datasource.length + '行</div>';
element.html(table);
table = '';
}
//根据列的别名获取原始列名
function getRawColumnName(friendlyCol) {
var rawCol;
//columnmap =[{name: 'Name'}, {street: 'Street'}, {age: 'Age'}, {url: 'URL', hidden: true}]
scope.columnmap.forEach(function(colMap) {
//{name: 'Name'}
for (var prop in colMap) {
if (colMap[prop] === friendlyCol) {
rawCol = prop;
break;
}
}
return null;
});
return rawCol;
}
function pushColumns(rawCol, renamedCol) {
visibleProps.push(rawCol);
scope.columns.push(renamedCol);
}
//比如根据name属性,这里得到[{name: 'Name'}]
//[{name: 'Name'}, {street: 'Street'}, {age: 'Age'}, {url: 'URL', hidden: true}]
function filterColumnMap(prop) {
var val = scope.columnmap.filter(function(map) {
if (map[prop]) {
return true;
}
return false;
});
return val;
} 
//根据原始列名获取列的别名,并考虑是否隐藏列的情况
function getColumnName(prop){
if(!scope.columnmap) return prop;
//得到[{name: 'Name'}]
var val = filterColumnMap(prop);
if(val && val.length && !val[0].hidden) return val[0][prop];
else return null;
}
};
return {
restrict: 'E',
scope: {
columnmap: '=',
datasource: '='
},
link:link,
template:template
};
};
angular.module('directiveModule')
.directive('tableHelper', tableHelper);
}());

以上所述是小编给大家分享的AngularJS中的Directive自定义一个表格的相关知识,希望对大家有所帮助。

[!--infotagslink--]

相关文章

  • 浅析AngularJS Filter用法

    系统的学习了一下angularjs,发现angularjs的有些思想根php的模块smarty很像,例如数据绑定,filter。如果对smarty比较熟悉的话,学习angularjs会比较容易一点,这篇文章给大家介绍angularjs filter用法详解,感兴趣的朋友一起学习吧...2015-12-29
  • AngularJS 实现按需异步加载实例代码

    AngularJS 通过路由支持多视图应用, 可以根据路由动态加载所需的视图, 在 AngularJS 的文档中有详细的介绍, 网上也有不少教程, 就不用介绍了!随着视图的不断增加,js文件会越来越多,而 AngularJS 默认需要把全部的js都一次性...2015-10-21
  • AngularJS实现分页显示数据库信息

    这篇文章主要为大家详细介绍了AngularJS实现分页显示数据库信息效果的相关资料,感兴趣的小伙伴们可以参考一下...2016-07-06
  • AngularJS 依赖注入详解及示例代码

    本文主要介绍AngularJS 依赖注入的知识,这里整理了相关的基础知识,并附示例代码和实现效果图,有兴趣的小伙伴可以参考下...2016-08-24
  • 基于jquery实现表格无刷新分页

    这篇文章主要介绍了基于jquery实现表格无刷新分页,功能实现了前端排序功能,增加了前端搜索功能,感兴趣的小伙伴们可以参考一下...2016-01-08
  • angularjs $http实现form表单提交示例

    这篇文章主要介绍了angularjs $http实现form表单提交示例,非常具有实用价值,需要的朋友可以参考下 ...2017-06-15
  • AngularJS实现Model缓存的方式

    这篇文章主要介绍了AngularJS实现Model缓存的方式,分享了多种AngularJS实现Model缓存的方法,感兴趣的小伙伴们可以参考一下...2016-02-05
  • AngularJS 视图详解及示例代码

    本文主要介绍AngularJS 视图,这里整理了相关知识,并附代码示例和实现效果图,有兴趣的小伙伴可以参考下...2016-08-27
  • AngularJS自定义指令之复制指令实现方法

    这篇文章主要介绍了AngularJS自定义指令之复制指令实现方法,结合完整实例形式分析了AngularJS自定义指令实现复制功能的相关操作技巧,需要的朋友可以参考下...2017-05-22
  • BootStrap和jQuery相结合实现可编辑表格

    这篇文章主要介绍了BootStrap和jQuery相结合实现可编辑表格的相关资料,需要的朋友可以参考下...2016-04-23
  • 浅谈AngularJs指令之scope属性详解

    下面小编就为大家带来一篇浅谈AngularJs指令之scope属性详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-25
  • AngularJs中route的使用方法和配置

    angular是Google开发的一个单页面应用框架,是现在比较主流的单页面应用框架之一,下面通过本文给大家介绍AngularJs中route的使用方法和配置,感兴趣的朋友一起学习吧...2016-02-09
  • vue.js表格分页示例

    这篇文章主要为大家详细介绍了vue.js表格分页示例,ajax异步加载数据...2016-10-20
  • 快速学习AngularJs HTTP响应拦截器

    任何时候,如果我们想要为请求添加全局功能,例如身份认证、错误处理等,在请求发送给服务器之前或服务器返回时对其进行拦截,是比较好的实现手段...2016-01-05
  • AngularJS使用ngOption实现下拉列表的实例代码

    这篇文章主要介绍了AngularJS使用ngOption实现下拉列表的实例代码的相关资料,需要的朋友可以参考下...2016-01-25
  • Angularjs中如何使用filterFilter函数过滤

    这篇文章主要介绍了Angularjs中如何使用filterFilter函数过滤的相关资料,需要的朋友可以参考下...2016-02-12
  • AngularJS 让人爱不释手的八种功能

    AngularJS 让人爱不释手的八种功能,想知道AngularJS哪八种功能让人喜欢就快点看下本文吧...2016-03-28
  • AngularJS内建服务$location及其功能详解

    这篇文章主要为大家详细介绍了AngularJS内建服务$location及$location功能,感兴趣的小伙伴们可以参考一下...2016-07-06
  • AngularJS表单详解及示例代码

    本文主要介绍AngularJS表单的知识,这里整理了表单的基础知识和简单的示例代码,有需要的小伙伴可以参考下...2016-08-24
  • Angularjs---项目搭建图文教程

    下面小编就为大家带来一篇Angularjs---项目搭建图文教程。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-07-25