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 相关文章推荐
flash 得到自身url参数的代码
Nov 15 Javascript
第一个JavaScript入门基础 document.write输出
Feb 22 Javascript
js截取中英文字符串、标点符号无乱码示例解读
Apr 17 Javascript
jQuery 2.0.3 源码分析之core(一)整体架构
May 27 Javascript
jquery中post方法用法实例
Oct 21 Javascript
在javascript中随机数 math random如何生成指定范围数值的随机数
Oct 21 Javascript
在 Angular 中使用Chart.js 和 ng2-charts的示例代码
Aug 17 Javascript
JavaScript查看代码运行效率console.time()与console.timeEnd()用法
Jan 18 Javascript
微信公众平台 客服接口发消息的实现代码(Java接口开发)
Apr 17 Javascript
Vue3项目打包后部署到服务器 请求不到后台接口解决方法
Feb 06 Javascript
vue实现登录拦截
Jun 29 Javascript
JavaScript实现简单图片切换
Apr 29 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
一些星际专用术语解释
2020/03/04 星际争霸
字母顺序颠倒而单词顺序不变的php代码
2010/08/08 PHP
ThinkPHP验证码使用简明教程
2014/03/05 PHP
PHP 数组遍历foreach语法结构及实例
2016/06/13 PHP
PHP单例模式应用示例【多次连接数据库只实例化一次】
2018/12/18 PHP
thinkphp5实现无限级分类
2019/02/18 PHP
laravel 5.5 关闭token的3种实现方式
2019/10/24 PHP
JavaScript window.setTimeout() 的详细用法
2009/11/04 Javascript
Javascript模块化编程(一)AMD规范(规范使用模块)
2013/01/17 Javascript
使用AngularJS制作一个简单的RSS阅读器的教程
2015/06/18 Javascript
让JavaScript中setTimeout支持链式操作的方法
2015/06/19 Javascript
javascript实现网页中涉及的简易运动(改变宽高、透明度、位置)
2015/11/29 Javascript
详解AngularJS中module模块的导入导出
2015/12/10 Javascript
JavaScript iframe数据共享接口实现方法
2016/01/06 Javascript
解决bootstrap导航栏navbar在IE8上存在缺陷的方法
2016/07/01 Javascript
微信小程序 教程之wxapp 视图容器 view
2016/10/19 Javascript
基于JavaScript实现的折半查找算法示例
2017/04/14 Javascript
Bootstrap组件之下拉菜单,多级菜单及按钮布局方法实例
2017/05/25 Javascript
微信小程序云开发之模拟后台增删改查
2019/05/16 Javascript
jquery.validate自定义验证用法实例分析【成功提示与择要提示】
2020/06/06 jQuery
vue穿梭框实现上下移动
2021/01/29 Vue.js
python模拟enum枚举类型的方法小结
2015/04/30 Python
Python对HTML转义字符进行反转义的实现方法
2019/04/28 Python
Python实现12306火车票抢票系统
2019/07/04 Python
django自定义模板标签过程解析
2019/12/14 Python
Django中Q查询及Q()对象 F查询及F()对象用法
2020/07/09 Python
使用纯 CSS 创作一个脉动 loader效果的源码
2018/09/28 HTML / CSS
维珍澳洲航空官网:Virgin Australia
2017/09/08 全球购物
当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
2014/09/09 面试题
客户服务经理岗位职责
2014/01/29 职场文书
见习期自我鉴定
2014/01/31 职场文书
简历自我评价模板
2015/03/11 职场文书
win11系统中dhcp服务异常什么意思? Win11 DHCP服务异常修复方法
2022/04/08 数码科技
详解如何使用Nginx解决跨域问题
2022/05/06 Servers
关于Redis的主从复制及哨兵问题
2022/06/16 Redis
windows10 家庭版下FTP服务器搭建教程
2022/08/05 Servers