Skip to content

Commit

Permalink
feat(ngTableDynamic): add a column on the fly
Browse files Browse the repository at this point in the history
Closes 602

Testing table header creation
Small example
  • Loading branch information
Jean-Yves LEBLEU authored and ccrowhurstram committed Jul 7, 2015
1 parent f469927 commit 0168277
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 5 deletions.
152 changes: 152 additions & 0 deletions examples/demo201.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">

<link rel="stylesheet" href="css/bootstrap.min.css">
<!--[if lt IE 9]>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<![endif]-->
<script src="../bower_components/angular/angular.js"></script>
<script src="../dist/ng-table.js"></script>
<link rel="stylesheet" href="../dist/ng-table.css">
</head>
<body ng-app="main">

<h1>Dynamic columns</h1>

<div ng-controller="DemoCtrl">
<div class="clearfix">
<button ng-click="changeCols()" class="btn btn-default pull-right">Change Cols</button>
<button ng-click="addColumn()" class="btn btn-default pull-right">add Column</button>
</div>

Columns:
<label class="checkbox" ng-repeat="column in cols">
<input type="checkbox" ng-model="column.show" /> {{column.title}}
</label>

<table ng-table-dynamic="tableParams with cols" show-filter="true" class="table table-bordered table-striped">
<tr ng-repeat="user in $data">
<td ng-repeat="col in $columns">{{user[col.field]}}</td>
</tr>
</table>

<script>
var app = angular.module('main', ['ngTable'])
.controller('DemoCtrl', function ($scope, $filter, $q, NgTableParams) {
var data = [
{name: "Moroni", age: 50, firstName: "John"},
{name: "Tiancum", age: 43, firstName: "ALice"},
{name: "Jacob", age: 27, firstName: "David"},
{name: "Nephi", age: 29, firstName: "Mary"},
{name: "Enos", age: 34, firstName: "Bea"},
{name: "Tiancum", age: 43, firstName: "ALice"},
{name: "Jacob", age: 27, firstName: "David"},
{name: "Nephi", age: 29, firstName: "Mary"},
{name: "Enos", age: 34, firstName: "Bea"},
{name: "Tiancum", age: 43, firstName: "ALice"},
{name: "Jacob", age: 27, firstName: "David"},
{name: "Nephi", age: 29, firstName: "Mary"},
{name: "Enos", age: 34, firstName: "Bea"},
{name: "Tiancum", age: 43, firstName: "ALice"},
{name: "Jacob", age: 27, firstName: "David"},
{name: "Nephi", age: 29, firstName: "Mary"},
{name: "Enos", age: 34, firstName: "Bea"},
];

$scope.changeNameTitle = function(){
usernameCol.title = "Crap!";
};

// terse - just return raw values
var usernameCol = {
title: 'Full Name',
titleAlt: 'Name',
sortable: 'name',
filter: { name: 'select' },
filterData: names,
show: true,
field: 'name'
};
// alternatively declare some/all column fields as functions
// your functions will receive the scope created for the header.html template as a parameter
var ageCol = {
title: 'Age',
sortable: function(/*paramsScope*/){
return 'age';
},
filter: function(/*paramsScope*/){
return {
age: 'text'
};
},
show: true,
field: 'age'
};
var firstNameCol = {
title: 'First Name',
titleAlt: 'Name',
sortable: 'firstName',
filter: { firstName: 'text' },
show: true,
field: 'firstName'
};
$scope.cols = [usernameCol, ageCol];

$scope.changeCols = function() {
$scope.cols = [ageCol, usernameCol];
};
$scope.addColumn = function() {
$scope.cols = [ageCol, usernameCol, firstNameCol];
};

function names() {
var def = $q.defer(),
arr = [],
names = [];
angular.forEach(data, function(item){
if (arr.indexOf(item.name) === -1) {
arr.push(item.name);
names.push({
'id': item.name,
'title': item.name
});
}
});
def.resolve(names);
return def;
}

$scope.tableParams = new NgTableParams({
page: 1, // show first page
count: 10 // count per page
}, {
filterDelay: 0,
total: data.length, // length of data
getData: function ($defer, params) {
// use build-in angular filter
var filteredData = params.filter() ?
$filter('filter')(data, params.filter()) :
data;
var orderedData = params.sorting() ?
$filter('orderBy')(filteredData, params.orderBy()) :
data;

params.total(orderedData.length);
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
})
</script>

</div>


</body>
</html>
11 changes: 6 additions & 5 deletions src/scripts/05-directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,16 @@ app.directive('ngTableDynamic', ['$parse', function ($parse){
el.attr('ng-show', '$columns[$index].show(this)');
}
});

return function(scope, element, attrs, controller) {
return function (scope, element, attrs, controller) {
var expr = parseDirectiveExpression(attrs.ngTableDynamic);
var columns = $parse(expr.columns)(scope) || [];
scope.$columns = controller.buildColumns(columns);

controller.setupBindingsToInternalScope(expr.tableParams);
controller.loadFilterData(scope.$columns);
controller.compileDirectiveTemplates();

scope.$watchCollection(expr.columns, function (newCols/*, oldCols*/) {
scope.$columns = controller.buildColumns(newCols);
controller.loadFilterData(scope.$columns);
});
};
}
};
Expand Down
87 changes: 87 additions & 0 deletions test/tableDynamicSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,94 @@ describe('ng-table-dynamic', function() {
expect(angular.element(dataCells[2]).attr('data-title-text').trim()).toBe('Money');
}));
});
describe('add column', function(){
var elm;
beforeEach(inject(function($compile, $q, NgTableParams) {
elm = angular.element(
'<div>' +
'<table ng-table-dynamic="tableParams with cols" show-filter="true">' +
'<tr ng-repeat="user in $data">' +
'<td ng-repeat="col in $columns">{{user[col.field]}}</td>' +
'</tr>' +
'</table>' +
'</div>');

function getCustomClass(parmasScope){
if (parmasScope.$column.title().indexOf('Money') !== -1){
return 'moneyHeaderClass';
} else{
return 'customClass';
}
}

function money(/*$column*/) {
var def = $q.defer();
def.resolve([{
'id': 10,
'title': '10'
}]);
return def;
}

scope.tableParams = new NgTableParams({}, {});
scope.cols = [
{
'class': getCustomClass,
field: 'name',
filter: { name: 'text' },
headerTitle: 'Sort by Name',
sortable: 'name',
show: true,
title: 'Name of person'
},
{
'class': getCustomClass,
field: 'age',
headerTitle: 'Sort by Age',
sortable: 'age',
show: true,
title: 'Age'
}
];

$compile(elm)(scope);
scope.$digest();
}));

it('should create table header', function() {
var newCol = {
'class': 'moneyadd',
field: 'money',
filter: { action: 'select' },
headerTitle: 'Sort by Money',
show: true,
title: 'Money'
};
scope.cols.push(newCol);
scope.$digest();
var thead = elm.find('thead');
expect(thead.length).toBe(1);

var rows = thead.find('tr');
expect(rows.length).toBe(2);

var titles = angular.element(rows[0]).find('th');

expect(titles.length).toBe(3);
expect(angular.element(titles[0]).text().trim()).toBe('Name of person');
expect(angular.element(titles[1]).text().trim()).toBe('Age');
expect(angular.element(titles[2]).text().trim()).toBe('Money');

expect(angular.element(rows[1]).hasClass('ng-table-filters')).toBeTruthy();
var filters = angular.element(rows[1]).find('th');
expect(filters.length).toBe(3);
expect(angular.element(filters[0]).hasClass('filter')).toBeTruthy();
expect(angular.element(filters[1]).hasClass('filter')).toBeTruthy();
expect(angular.element(filters[2]).hasClass('filter')).toBeTruthy();

});

});
describe('title-alt', function() {

var elm;
Expand Down

0 comments on commit 0168277

Please sign in to comment.