先給大家說下表格的需求:
● 表格結構
<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自訂一個表格的相關知識,希望對大家有所協助。