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 相关文章推荐
Mootools 1.2教程 同时进行多个形变动画
Sep 15 Javascript
jquery Mobile入门—多页面切换示例学习
Jan 08 Javascript
Node.js中使用Log.io在浏览器中实时监控日志(等同tail -f命令)
Sep 17 Javascript
jquery.gridrotator实现响应式图片展示画廊效果
Jun 23 Javascript
基于JS判断iframe是否加载成功的方法(多种浏览器)
May 13 Javascript
浅谈bootstrap源码分析之scrollspy(滚动侦听)
Jun 06 Javascript
移动端翻页插件dropload.js(支持Zepto和jQuery)
Jul 27 Javascript
深入理解bootstrap框架之第二章整体架构
Oct 09 Javascript
boostrapTable的refresh和refreshOptions区别浅析
Jan 22 Javascript
Canvas + JavaScript 制作图片粒子效果
Feb 08 Javascript
PWA介绍及快速上手搭建一个PWA应用的方法
Jan 27 Javascript
如何实现小程序tab栏下划线动画效果
May 18 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
使用无限生命期Session的方法
2006/10/09 PHP
在PHP中养成7个面向对象的好习惯
2010/01/28 PHP
PHP 自定义错误处理函数trigger_error()
2013/03/26 PHP
获取php页面执行时间,数据库读写次数,函数调用次数等(THINKphp)
2013/06/03 PHP
PHP+FFMPEG实现将视频自动转码成H264标准Mp4文件
2014/09/24 PHP
列举PHP的Yii 2框架的开发优势
2015/07/03 PHP
基于PHP技术开发客服工单系统
2016/01/06 PHP
浅谈laravel 5.6 安装 windows上使用composer的安装过程
2019/10/18 PHP
jquery mobile实现拨打电话功能的几种方法
2013/08/05 Javascript
Js base64 加密解密介绍
2013/10/11 Javascript
JavaScript cookie的设置获取删除详解
2014/02/11 Javascript
使用AngularJS制作一个简单的RSS阅读器的教程
2015/06/18 Javascript
js实现input框文字动态变换显示效果
2015/08/19 Javascript
jQuery1.9.1源码分析系列(十六)ajax之ajax框架
2015/12/04 Javascript
JavaScript基础——使用Canvas绘图
2016/11/02 Javascript
jQuery Ajax实现跨域请求
2017/01/21 Javascript
canvas实现图片根据滑块放大缩小效果
2017/02/24 Javascript
详解vue.js 开发环境搭建最简单攻略
2017/06/12 Javascript
JS库之ParticlesJS使用简介
2017/09/12 Javascript
Vue.js中provide/inject实现响应式数据更新的方法示例
2019/10/16 Javascript
关于angular浏览器兼容性问题的解决方案
2020/07/26 Javascript
win7 下搭建sublime的python开发环境的配置方法
2014/06/18 Python
Python中使用md5sum检查目录中相同文件代码分享
2015/02/02 Python
简单介绍使用Python解析并修改XML文档的方法
2015/10/15 Python
Pycharm 设置自定义背景颜色的图文教程
2018/05/23 Python
WxPython实现无边框界面
2019/11/18 Python
python构建指数平滑预测模型示例
2019/11/21 Python
世界上最大的餐具公司:Oneida
2016/12/17 全球购物
什么是反射?如何实现反射?
2016/07/25 面试题
移动通信行业实习自我鉴定
2013/09/28 职场文书
大学生简短的自我评价分享
2014/02/20 职场文书
信息学院毕业生自荐信范文
2014/03/04 职场文书
留学生求职信
2014/06/03 职场文书
房屋授权无偿使用证明
2014/11/29 职场文书
《时代广场的蟋蟀》读后感:真挚友情,温暖世界!
2020/01/08 职场文书
Python制作一个随机抽奖小工具的实现
2021/07/07 Python