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中的undefined,null,&quot;&quot;,0和false
Mar 08 Javascript
prototype Element学习笔记(Element篇三)
Oct 26 Javascript
js模仿html5 placeholder适应于不支持的浏览器
Jan 13 Javascript
多次注册事件会导致一个事件被触发多次的解决方法
Aug 12 Javascript
详解Bootstrap glyphicons字体图标
Jan 04 Javascript
Bootstrap3制作自己的导航栏
May 12 Javascript
js图片上传前预览功能(兼容所有浏览器)
Aug 24 Javascript
Vue.js项目中管理每个页面的头部标签的两种方法
Jun 25 Javascript
vue-cli 3.x 修改dist路径的方法
Sep 19 Javascript
Vue插件从封装到发布的完整步骤记录
Feb 28 Javascript
layui 关闭open弹出框 刷新table表格页面的方法
Sep 16 Javascript
jQuery实现高度灵活的表单验证功能示例【无UI】
Apr 30 jQuery
理解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数据库连接
2006/10/09 PHP
php获取当前网址url并替换参数或网址的方法
2010/06/06 PHP
php常用Output和ptions/Info函数集介绍
2013/06/19 PHP
ThinkPHP中数据操作案例分析
2015/09/27 PHP
PHP读取文件,解决中文乱码UTF-8的方法分析
2020/01/22 PHP
20个非常有用的PHP类库 加速php开发
2010/01/15 Javascript
Javascript 面向对象 命名空间
2010/05/13 Javascript
理解Javascript_15_作用域分配与变量访问规则,再送个闭包
2010/10/20 Javascript
基于promise.js实现nodejs的promises库
2014/07/06 NodeJs
jquery处理页面弹出层查询数据等待操作实例
2015/03/25 Javascript
浅析在javascript中创建对象的各种模式
2016/05/06 Javascript
用jmSlip编写移动端顶部日历选择控件
2016/10/24 Javascript
利用node.js搭建简单web服务器的方法教程
2017/02/20 Javascript
Echarts地图添加引导线效果(labelLine)
2019/09/30 Javascript
python登录并爬取淘宝信息代码示例
2017/12/09 Python
python2.7到3.x迁移指南
2018/02/01 Python
GitHub 热门:Python 算法大全,Star 超过 2 万
2019/04/29 Python
python替换字符串中的子串图文步骤
2019/06/19 Python
Python:Numpy 求平均向量的实例
2019/06/29 Python
Django 迁移、操作数据库的方法
2019/08/02 Python
python中with用法讲解
2020/02/07 Python
基于Pytorch SSD模型分析
2020/02/18 Python
DataFrame 数据合并实现(merge,join,concat)
2020/06/14 Python
在django中查询获取数据,get, filter,all(),values()操作
2020/08/09 Python
python 8种必备的gui库
2020/08/27 Python
Python+OpenCV图像处理——打印图片属性、设置存储路径、调用摄像头
2020/10/22 Python
Python爬虫分析微博热搜关键词的实现代码
2021/02/22 Python
C#的几个面试问题
2016/05/22 面试题
入党自我鉴定范文
2013/10/04 职场文书
大学生求职信例文
2014/06/29 职场文书
毕业设计致谢语
2015/05/14 职场文书
初中班主任教育随笔
2015/08/15 职场文书
python自动统计zabbix系统监控覆盖率的示例代码
2021/04/03 Python
react合成事件与原生事件的相关理解
2021/05/13 Javascript
python opencv旋转图片的使用方法
2021/06/04 Python
box-shadow单边阴影的实现
2023/05/21 HTML / CSS