blob: c2fe85d130232a38f23d31f430d2113f69adec3d [file] [log] [blame]
Matteo Scandolo91fe03d2016-03-24 15:29:52 -07001/**
2 * © OpenCORD
3 *
4 * Visit http://guide.xosproject.org/devguide/addview/ for more information
5 *
6 * Created by teone on 3/24/16.
7 */
8
9(function () {
10 'use strict';
11
Matteo Scandolocc6954e2016-04-15 12:20:14 -070012 angular.module('xos.uiComponents')
Matteo Scandoloaa683dd2016-04-14 15:34:12 -070013
14 /**
15 * @ngdoc directive
Matteo Scandoloe15a8202016-04-15 14:27:54 -070016 * @name xos.uiComponents.directive:xosTable
Matteo Scandoloaa683dd2016-04-14 15:34:12 -070017 * @restrict E
18 * @description The xos-table directive
Matteo Scandoloa6a9e612016-04-14 16:52:13 -070019 * @param {Object} config The configuration for the component.
20 * ```
21 * {
22 * columns: [
23 * {
24 * label: 'Human readable name',
25 * prop: 'Property to read in the model object'
26 * }
27 * ],
28 * classes: 'table table-striped table-bordered',
29 * actions: [ // if defined add an action column
30 {
31 label: 'delete',
32 icon: 'remove', // refers to bootstraps glyphicon
33 cb: (user) => { // receive the model
34 console.log(user);
35 },
36 color: 'red'
37 }
Matteo Scandolo5677bb12016-04-14 17:21:45 -070038 ],
39 filter: 'field', // can be by `field` or `fulltext`
40 order: true // whether to show ordering arrows
Matteo Scandoloa6a9e612016-04-14 16:52:13 -070041 * }
42 * ```
43 * @param {Array} data The data that should be rendered
Matteo Scandoloaa683dd2016-04-14 15:34:12 -070044 * @element ANY
45 * @scope
46 * @example
47
Matteo Scandoloe15a8202016-04-15 14:27:54 -070048 <example module="sampleTable1">
Matteo Scandoloaa683dd2016-04-14 15:34:12 -070049 <file name="index.html">
50 <div ng-controller="SampleCtrl1 as vm">
51 <xos-table data="vm.data" config="vm.config"></xos-table>
Matteo Scandoloaa683dd2016-04-14 15:34:12 -070052 </div>
53 </file>
54 <file name="script.js">
Matteo Scandoloe15a8202016-04-15 14:27:54 -070055 angular.module('sampleTable1', ['xos.uiComponents'])
Matteo Scandoloaa683dd2016-04-14 15:34:12 -070056 .controller('SampleCtrl1', function(){
57 this.config = {
58 columns: [
59 {
Matteo Scandoloa6a9e612016-04-14 16:52:13 -070060 label: 'First Name', // column title
61 prop: 'name' // property to read in the data array
Matteo Scandoloaa683dd2016-04-14 15:34:12 -070062 },
63 {
64 label: 'Last Name',
65 prop: 'lastname'
66 }
67 ]
68 };
69
70 this.data = [
71 {
72 name: 'John',
73 lastname: 'Doe'
74 },
75 {
76 name: 'Gili',
77 lastname: 'Fereydoun'
78 }
79 ]
80 });
81 </file>
82 </example>
83
Matteo Scandolo88e18462016-04-25 14:24:18 -070084 <example module="sampleTable2" animations="true">
Matteo Scandoloaa683dd2016-04-14 15:34:12 -070085 <file name="index.html">
86 <div ng-controller="SampleCtrl2 as vm">
87 <xos-table data="vm.data" config="vm.config"></xos-table>
Matteo Scandoloaa683dd2016-04-14 15:34:12 -070088 </div>
89 </file>
90 <file name="script.js">
Matteo Scandolo88e18462016-04-25 14:24:18 -070091 angular.module('sampleTable2', ['xos.uiComponents', 'ngAnimate'])
Matteo Scandoloaa683dd2016-04-14 15:34:12 -070092 .controller('SampleCtrl2', function(){
93 this.config = {
94 columns: [
95 {
Matteo Scandoloa6a9e612016-04-14 16:52:13 -070096 label: 'First Name', // column title
97 prop: 'name' // property to read in the data array
Matteo Scandoloaa683dd2016-04-14 15:34:12 -070098 },
99 {
100 label: 'Last Name',
101 prop: 'lastname'
102 }
103 ],
Matteo Scandoloa6a9e612016-04-14 16:52:13 -0700104 classes: 'table table-striped table-condensed', // table classes, default to `table table-striped table-bordered`
105 actions: [ // if defined add an action column
Matteo Scandoloaa683dd2016-04-14 15:34:12 -0700106 {
Matteo Scandoloa6a9e612016-04-14 16:52:13 -0700107 label: 'delete', // label
108 icon: 'remove', // icons, refers to bootstraps glyphicon
109 cb: (user) => { // callback, get feeded with the full object
Matteo Scandoloaa683dd2016-04-14 15:34:12 -0700110 console.log(user);
111 },
Matteo Scandoloa6a9e612016-04-14 16:52:13 -0700112 color: 'red' // icon color
Matteo Scandoloaa683dd2016-04-14 15:34:12 -0700113 }
Matteo Scandolo5677bb12016-04-14 17:21:45 -0700114 ],
115 filter: 'field', // can be by `field` or `fulltext`
116 order: true
Matteo Scandoloaa683dd2016-04-14 15:34:12 -0700117 };
118
119 this.data = [
120 {
121 name: 'John',
122 lastname: 'Doe'
123 },
124 {
125 name: 'Gili',
126 lastname: 'Fereydoun'
127 }
128 ]
129 });
130 </file>
131 </example>
132
Matteo Scandoloe15a8202016-04-15 14:27:54 -0700133 <example module="sampleTable3">
134 <file name="index.html">
135 <div ng-controller="SampleCtrl3 as vm">
136 <xos-table data="vm.data" config="vm.config"></xos-table>
137 </div>
138 </file>
139 <file name="script.js">
140 angular.module('sampleTable3', ['xos.uiComponents'])
141 .controller('SampleCtrl3', function(){
142 this.config = {
143 columns: [
144 {
145 label: 'First Name', // column title
146 prop: 'name' // property to read in the data array
147 },
148 {
149 label: 'Last Name',
150 prop: 'lastname'
151 }
152 ],
153 pagination: {
154 pageSize: 2
155 }
156 };
157
158 this.data = [
159 {
160 name: 'John',
161 lastname: 'Doe'
162 },
163 {
164 name: 'Gili',
165 lastname: 'Fereydoun'
166 },
167 {
168 name: 'Lucky',
169 lastname: 'Clarkson'
170 },
171 {
172 name: 'Tate',
173 lastname: 'Spalding'
174 }
175 ]
176 });
177 </file>
178 </example>
Matteo Scandoloaa683dd2016-04-14 15:34:12 -0700179 **/
180
Matteo Scandolo91fe03d2016-03-24 15:29:52 -0700181 .directive('xosTable', function(){
182 return {
183 restrict: 'E',
184 scope: {
185 data: '=',
Matteo Scandolo18adcb52016-04-14 12:06:50 -0700186 config: '='
Matteo Scandolo91fe03d2016-03-24 15:29:52 -0700187 },
Matteo Scandolob7a86dc2016-04-14 11:46:30 -0700188 template: `
Matteo Scandoloe15a8202016-04-15 14:27:54 -0700189 <div ng-show="vm.data.length > 0">
190 <div class="row" ng-if="vm.config.filter == 'fulltext'">
191 <div class="col-xs-12">
192 <input
193 class="form-control"
194 placeholder="Type to search.."
195 type="text"
196 ng-model="vm.query"/>
197 </div>
198 </div>
Matteo Scandolob0280752016-04-25 10:31:22 -0700199 <table ng-class="vm.classes" ng-hide="vm.data.length == 0">
Matteo Scandoloe15a8202016-04-15 14:27:54 -0700200 <thead>
201 <tr>
202 <th ng-repeat="col in vm.columns">
203 {{col.label}}
204 <span ng-if="vm.config.order">
205 <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = false">
206 <i class="glyphicon glyphicon-chevron-up"></i>
207 </a>
208 <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = true">
209 <i class="glyphicon glyphicon-chevron-down"></i>
210 </a>
211 </span>
212 </th>
Matteo Scandolodc249eb2016-04-26 11:44:36 -0700213 <th ng-if="vm.config.actions">Actions:</th>
Matteo Scandoloe15a8202016-04-15 14:27:54 -0700214 </tr>
215 </thead>
216 <tbody ng-if="vm.config.filter == 'field'">
217 <tr>
218 <td ng-repeat="col in vm.columns">
219 <input
220 class="form-control"
221 placeholder="Type to search by {{col.label}}"
222 type="text"
223 ng-model="vm.query[col.prop]"/>
224 </td>
225 <td ng-if="vm.config.actions"></td>
226 </tr>
227 </tbody>
228 <tbody>
229 <tr ng-repeat="item in vm.data | filter:vm.query | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">
Matteo Scandolof9700a32016-05-06 09:42:45 -0700230 <td ng-repeat="col in vm.columns">
231 <span ng-if="!col.type">{{item[col.prop]}}</span>
232 <span ng-if="col.type === 'boolean'">
233 <i class="glyphicon"
234 ng-class="{'glyphicon-ok': item[col.prop], 'glyphicon-remove': !item[col.prop]}">
235 </i>
236 </span>
237 <span ng-if="col.type === 'date'">
238 {{item[col.prop] | date:'H:mm MMM d, yyyy'}}
239 </span>
240 <span ng-if="col.type === 'array'">
241 {{item[col.prop] | arrayToList}}
242 </span>
Matteo Scandolo58705a42016-05-06 10:08:34 -0700243 <span ng-if="col.type === 'object'">
244 <dl class="dl-horizontal" ng-repeat="(k,v) in item[col.prop]">
245 <dt>{{k}}</dt>
246 <dd>{{v}}</dd>
247 </dl>
248 </span>
Matteo Scandolof9700a32016-05-06 09:42:45 -0700249 <span ng-if="col.type === 'custom'">
250 {{col.formatter(item[col.prop])}}
251 </span>
252 </td>
Matteo Scandoloe15a8202016-04-15 14:27:54 -0700253 <td ng-if="vm.config.actions">
254 <a href=""
255 ng-repeat="action in vm.config.actions"
256 ng-click="action.cb(item)"
257 title="{{action.label}}">
258 <i
259 class="glyphicon glyphicon-{{action.icon}}"
260 style="color: {{action.color}};"></i>
261 </a>
262 </td>
263 </tr>
264 </tbody>
265 </table>
266 <xos-pagination
267 ng-if="vm.config.pagination"
268 page-size="vm.config.pagination.pageSize"
269 total-elements="vm.data.length"
270 change="vm.goToPage">
271 </xos-pagination>
272 </div>
273 <div ng-show="vm.data.length == 0 || !vm.data">
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700274 <xos-alert config="{type: 'info'}">
Matteo Scandoloe15a8202016-04-15 14:27:54 -0700275 No data to show.
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700276 </xos-alert>
Matteo Scandoloa6a9e612016-04-14 16:52:13 -0700277 </div>
Matteo Scandolob7a86dc2016-04-14 11:46:30 -0700278 `,
Matteo Scandolo91fe03d2016-03-24 15:29:52 -0700279 bindToController: true,
280 controllerAs: 'vm',
Matteo Scandolof9700a32016-05-06 09:42:45 -0700281 controller: function(_){
Matteo Scandolo18adcb52016-04-14 12:06:50 -0700282
283 if(!this.config){
284 throw new Error('[xosTable] Please provide a configuration via the "config" attribute');
285 }
286
287 if(!this.config.columns){
288 throw new Error('[xosTable] Please provide a columns list in the configuration');
289 }
290
Matteo Scandolof9700a32016-05-06 09:42:45 -0700291 // if columns with type 'custom' are provide
292 // check that a custom formatted is provided too
293 let customCols = _.filter(this.config.columns, {type: 'custom'});
294 if(angular.isArray(customCols) && customCols.length > 0){
295 _.forEach(customCols, (col) => {
296 if(!col.formatter){
297 throw new Error('[xosTable] You have provided a custom field type, a formatter function should provided too.');
298 }
299 })
300 }
301
Matteo Scandolo18adcb52016-04-14 12:06:50 -0700302 this.columns = this.config.columns;
303 this.classes = this.config.classes || 'table table-striped table-bordered';
304
Matteo Scandolo9e6c6fc2016-04-14 14:59:09 -0700305 if(this.config.actions){
Matteo Scandolocc6954e2016-04-15 12:20:14 -0700306 // TODO validate action format
307 }
308 if(this.config.pagination){
309 this.currentPage = 0;
310 this.goToPage = (n) => {
311 this.currentPage = n;
312 };
Matteo Scandolo9e6c6fc2016-04-14 14:59:09 -0700313 }
314
Matteo Scandolo91fe03d2016-03-24 15:29:52 -0700315 }
316 }
317 })
Matteo Scandolof9700a32016-05-06 09:42:45 -0700318.filter('arrayToList', function(){
319 return (input) => {
320 if(!angular.isArray(input)){
Matteo Scandolo58705a42016-05-06 10:08:34 -0700321 return input;
Matteo Scandolof9700a32016-05-06 09:42:45 -0700322 }
323 return input.join(', ');
324 }
325});
Matteo Scandolo91fe03d2016-03-24 15:29:52 -0700326})();