AngularJS中的Directive自定义一个表格


Posted in Javascript onJanuary 25, 2016

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

● 表格结构

<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自定义一个表格的相关知识,希望对大家有所帮助。

Javascript 相关文章推荐
js验证表单大全
Nov 25 Javascript
提高网站信任度的技巧
Oct 17 Javascript
jQuery实现的Email中的收件人效果(按del键删除)
Mar 20 Javascript
自己实现string的substring方法 人民币小写转大写,数字反转,正则优化
Sep 02 Javascript
jQuery Ajax提交表单查询获得数据实例代码
Sep 19 Javascript
javascript实现的DES加密示例
Oct 30 Javascript
自己动手手写jQuery插件总结
Jan 20 Javascript
js兼容火狐获取图片宽和高的方法
May 21 Javascript
vue组件实例解析
Jan 10 Javascript
Vue-resource拦截器判断token失效跳转的实例
Oct 27 Javascript
三分钟学会用ES7中的Async/Await进行异步编程
Jun 14 Javascript
Vue源码中要const _toStr = Object.prototype.toString的原因分析
Dec 09 Javascript
理解JavaScript事件对象
Jan 25 #Javascript
AngularJS中如何使用$parse或$eval在运行时对Scope变量赋值
Jan 25 #Javascript
学习JavaScript事件流和事件处理程序
Jan 25 #Javascript
javascript产生随机数方法汇总
Jan 25 #Javascript
在AngularJS中如何使用谷歌地图把当前位置显示出来
Jan 25 #Javascript
理解JavaScript表单的基础知识
Jan 25 #Javascript
jquery获取文档高度和窗口高度汇总
Jan 25 #Javascript
You might like
配置php网页显示各种语法错误
2013/09/23 PHP
通过php修改xml文档内容的方法
2015/01/23 PHP
WordPress中用于获取文章信息以及分类链接的函数用法
2015/12/18 PHP
纯js实现遮罩层效果原理分析
2014/05/27 Javascript
js的[defer]和[async]属性
2014/11/24 Javascript
node.js中的path.join方法使用说明
2014/12/08 Javascript
解决node-webkit 不支持html5播放mp4视频的方法
2015/03/11 Javascript
创建自己的jquery表格插件
2015/11/25 Javascript
JavaScript 数组some()和filter()的用法及区别
2016/05/20 Javascript
jQuery展示表格点击变色、全选、删除
2017/01/05 Javascript
angularjs封装$http为factory的方法
2017/05/18 Javascript
在vue项目中引入highcharts图表的方法(详解)
2018/03/05 Javascript
基于Vue实现微信小程序的图文编辑器
2018/07/25 Javascript
在vue-cli的组件模板里使用font-awesome的两种方法
2018/09/28 Javascript
详解微信小程序与内嵌网页交互实现支付功能
2018/10/22 Javascript
JS实现拼图游戏
2021/01/29 Javascript
js实现无缝轮播图特效
2020/05/09 Javascript
JS实现简易日历效果
2021/01/25 Javascript
[01:34]DAC2018主赛事第四日五佳镜头 Gh巨牙海民助Miracle-死里逃生
2018/04/07 DOTA
python连接mongodb操作数据示例(mongodb数据库配置类)
2013/12/31 Python
Python中用pycurl监控http响应时间脚本分享
2015/02/02 Python
谈谈Python进行验证码识别的一些想法
2016/01/25 Python
使用Kivy将python程序打包为apk文件
2017/07/29 Python
python自动重试第三方包retrying模块的方法
2018/04/24 Python
python中cPickle类使用方法详解
2018/08/27 Python
python使用epoll实现服务端的方法
2018/10/16 Python
python字典的遍历3种方法详解
2019/08/10 Python
jupyter notebook运行命令显示[*](解决办法)
2020/05/18 Python
python中remove函数的踩坑记录
2021/01/04 Python
粉红色的鲸鱼:Vineyard Vines
2018/02/17 全球购物
服装设计专业毕业生推荐信
2013/11/09 职场文书
英语专业个人求职信范文
2014/02/01 职场文书
新学期国旗下演讲稿
2014/05/08 职场文书
机关作风建设剖析材料
2014/10/11 职场文书
2015年乡镇财政工作总结
2015/05/19 职场文书
小学体育课教学反思
2016/02/16 职场文书