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 相关文章推荐
splice slice区别
Oct 09 Javascript
js中将字符串转换成json的三种方式
Jan 12 Javascript
jQuery 常见操作实现方式和常用函数方法总结
May 06 Javascript
悬浮数字的实现案例
Feb 19 Javascript
js中document.write的那点事
Dec 12 Javascript
jQuery中:first选择器用法实例
Dec 30 Javascript
PHP中CURL的几个经典应用实例
Jan 23 Javascript
jQuery实现防止提交按钮被双击的方法
Mar 24 Javascript
详解Node.js模板引擎Jade入门
Jan 19 Javascript
解决Vue在封装了Axios后手动刷新页面拦截器无效的问题
Nov 08 Javascript
微信小程序 拍照或从相册选取图片上传代码实例
Aug 28 Javascript
详解Node.js如何处理ES6模块
May 15 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 mssql扩展SQL查询中文字段名解决方法
2012/10/15 PHP
php pthreads多线程的安装与使用
2016/01/19 PHP
实例讲解php数据访问
2016/05/09 PHP
ThinkPHP3.2.2实现持久登录(记住我)功能的方法
2016/05/16 PHP
PHP获取用户访问IP地址的5种方法
2016/05/16 PHP
总结的一些PHP开发中的tips(必看篇)
2017/03/24 PHP
PHP对称加密算法(DES/AES)类的实现代码
2017/11/14 PHP
不一样的文字闪烁 轮番闪烁
2009/11/11 Javascript
Javascript(AJAX)解析XML的代码(兼容FIREFOX/IE)
2010/07/11 Javascript
js 纯数字不重复排列的另类方法
2010/07/17 Javascript
查找Oracle高消耗语句的方法
2014/03/22 Javascript
JavaScript DSL 流畅接口(使用链式调用)实例
2015/03/15 Javascript
js实现touch移动触屏滑动事件
2015/04/17 Javascript
创建一个类Person的简单实例
2016/05/17 Javascript
javascript设置文本框光标的方法实例小结
2016/11/04 Javascript
Vue.js第二天学习笔记(vue-router)
2016/12/01 Javascript
javascript字体颜色控件的开发 JS实现字体控制
2017/11/27 Javascript
Bootstrap 模态框多次显示后台提交多次BUG的解决方法
2017/12/26 Javascript
JavaScript适配器模式原理与用法实例详解
2020/03/09 Javascript
Vue——解决报错 Computed property &quot;****&quot; was assigned to but it has no setter.
2020/12/19 Vue.js
python实现linux服务器批量修改密码并生成execl
2014/04/22 Python
Python中利用sorted()函数排序的简单教程
2015/04/27 Python
使用Python的PIL模块来进行图片对比
2016/02/18 Python
如何安装多版本python python2和python3共存以及pip共存
2018/09/18 Python
Tensorflow实现在训练好的模型上进行测试
2020/01/20 Python
Python API len函数操作过程解析
2020/03/05 Python
python微信公众号开发简单流程实现
2020/03/09 Python
Pycharm Plugins加载失败问题解决方案
2020/11/28 Python
TensorFlow低版本代码自动升级为1.0版本
2021/02/20 Python
某同学的自我鉴定范文
2013/12/26 职场文书
《守株待兔》教学反思
2014/03/01 职场文书
幼儿园中班下学期评语
2014/04/18 职场文书
社会调查研究计划书
2014/05/01 职场文书
初中生旷课检讨书范文
2014/10/06 职场文书
2016年秋季运动会广播稿
2015/12/21 职场文书
使用jpa之动态插入与修改(重写save)
2021/11/23 Java/Android