Suppose I would like to write a reusable + universal directive that will be used throughout my whole project. This directive will be displaying a table, as follows:
angular
.module('demo')
.directive('indexTable', function() {
return {
restrict: 'A',
template: '<tr ng-repeat=" component in components>' +
'<td ng-repeat="obj in component">' +
'{{obj}}' +
'</td>' +
'</tr>',
scope: {
components: '=',
},
link: function (scope, attrs) {
}
}
});
Supposing in my controller I have two different arrays with each two sets of different objects with different properties:
//some mockup data
angular.module('demo')
.controller('demoCtrl',['$scope',function($scope){
//array 1
$scope.userArray = [
{Id:1 , Name: 'Chuck Norris', Age:'21'},
{Id:2 , Name: 'George Bush' , Age: '42'}
];
//array 2
$scope.itemArray = [
{Id:1, ProductNo: '001', BasePrice: 20.20, Value: 50.50}
{Id:2, ProductNo: '002', BasePrice: 20.20, Value: 50.50}
];
}]);
So basically the question is: How do I select (in controller) what are the properties to be displayed in the table?
Question In-Depth : Now I have two different arrays with each of their own properties. How I would use it in my HTML will be
<div index-table components="userArray"></div>
Take the itemArray
for example. Each object will have 4 properties, namely Id
, ProductNo
, etc. But in my table, I would only want to display 2 of which, say only ProductNo
and BasePrice
. How do I discard the other two properties that I do not want? As you can see from my partial template there, I am using double ng-repeats
.
Things I have considered / tried so far: Tried Mapping objects to array, but I believe ng-repeat
is far more intelligent. Do I need to add in more scope attributes? How do I write my link function? Any ideas?
You can pass an attribute defining the property names that will populate each column. E.g.:
<table index-table
components="itemArray"
columns="ProductNo,BasePrice"
></table>
Your directive has to be slightly modified:
app.directive('indexTable', function() {
function parseProps(str) {
// implement parse logic, return an array of strings - the property names
}
return {
restrict: 'A',
template:
'<tr ng-repeat="component in components">' +
'<td ng-repeat="name in props">' +
'{{ component[name] }}' +
'</td>' +
'</tr>',
scope: {
components: '='
},
link: function (scope, elem, attrs) {
scope.props = parseProps(attrs.columns);
}
};
});
You can see a sample implementation here: http://jsfiddle.net/y54x0hcd/
This has a lot of rough edges (e.g.: column titles?); maybe it would be better to use a grid library.