先给大家说下表格的需求:
● 表格结构<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自定义一个表格的相关知识,希望对大家有所帮助。