-
Notifications
You must be signed in to change notification settings - Fork 83
/
px-data-table.html
584 lines (523 loc) · 20.7 KB
/
px-data-table.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
<!--
Copyright (c) 2018, General Electric
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<link rel="import" href="../polymer/polymer.html"/>
<link rel="import" href="aha-table.html"/>
<link rel="import" href="px-data-table-column.html"/>
<link rel="import" href="px-data-table-highlight.html"/>
<link rel="import" href="../px-validation/px-validation.html"/>
<link rel="import" href="../app-localize-behavior/app-localize-behavior.html"/>
<link rel="import" href="css/px-data-table-styles.html"/>
<!--
Element that defines a data table, optionally using a sub-element for advanced column settings.
Use the dropdown at the top of this screen to see documentation on the `px-data-table-column` and `px-data-table-highlight` sub-components.
### Client-Side VS Server-Side Data Paradigms
There are two main paradigms for the source of data in a table.
In a *Client-Side* model, the browser makes one request for the _complete set_ of data.
This means that sorting, filtering, and pagination all happen in memory on the client.
While this produces snappy tables with reasonably sized data sets, it can lead to a sluggish UI
for larger data sets. This works great with data sets that don't change frequently,
since the full payload would have to be resent for every update.
In a *Server-Side* model, the browser makes a request for a _subset_ of data for a particular page.
Sorting, filtering, and pagination requests will have to be made to a service for a new _subset_ of data
that matches the user's intended criteria. This prevents the browser from being overwhelmed with excessively
large data sets by only exposing one page's worth of data at a time. This is ideal for larger data sets or
where it is preferable to make multiple small requests instead of fewer larger requests. Due to the increased
frequency of requests, the UI is more likely to display data in sync with the server.
### Client-Side Data Usage
See the `README.md` and `docs` files in the repo for more details and advanced examples.
Minimum:
<px-data-table table-data="{{data}}"></px-data-table>
Advanced:
<px-data-table filterable selectable striped table-data="{{data}}">
// See px-data-table-column API using dropdown at top of screen.
<px-data-table-column name="first" ...></px-data-table-column>
<px-data-table-column name="last" ...></px-data-table-column>
<px-data-table-column name="color" ...></px-data-table-column>
<px-data-table-column name="date" ...></px-data-table-column>
</px-data-table>
### Server-Side Data Usage
See the `README.md` and `docs` files in the repo for more details and advanced examples.
For container element `ContainerEl`, create the following event listeners and request new data based on the user-intended change. Upon receiving updated data, update the variables bound to the `table-data`, `total-entries`, and `first-item-index` attributes.
Minimum:
<px-data-table
total-entries="100"
first-item-index="11"
table-data="{{dataSubset}}"
remote-data="true"
>
</px-data-table>
Advanced:
In the following example `serverResponse` is an object that is updated upon the response of a server.
<px-data-table
id="remoteDataTable"
total-entries="{{serverResponse.totalRecordsCount}}"
first-item-index="{{serverResponse.recordIndexOfSubset}}"
table-data="{{serverResponse.dataSubset}}"
remote-data="true"
>
<px-data-table-column
name="first"
sortable
filter-function-name="myTableCustomFunctions.filterWholeWord"
sort-function-name="myTableCustomFunctions.sortByEmailDomain">
</px-data-table-column>
<px-data-table-column name="last"></px-data-table-column>
<px-data-table-column name="color"></px-data-table-column>
<px-data-table-column name="date"></px-data-table-column>
</px-data-table>
### Integrating with other frameworks (ex: Angular):
You may not be able to use 2-way binding with the objects/arrays in other frameworks such as Angular.
We suggest instead to use events and selectors, for example:
document.getElementById("myDataTable").addEventListener("px-row-click", function(e) {
...
});
document.getElementById("myDataTable").addEventListener("px-select-all-click", function(e) {
...
});
$scope.doSomethingWithSelectedRows = function() {
$scope.allSelectedRows = document.getElementById("myDataTable").selectedRows;
};
### Styling
The following custom properties are available for styling:
Custom property | Description
----------------|-------------
`--px-data-table-border-color` | The table border color
`--px-data-table-separator-color` | The table separator color
`--px-data-table-header-text-color` | The text color of header rows
`--px-data-table-header-background-color` | The background color of header rows
`--px-data-table-row-background-color--hover` | The background color of a row when hovered
`--px-data-table-row-cursor--hover` | The cursor style of a row when hovered
`--px-data-table-cell-border-color--edit` | The cell border color when in edit mode
`--px-data-table-cell-border-color--selected` | The cell border color when selected
`--px-data-table-cell-border-validation--failed` | The cell border color when validation fails
`--px-data-table-cell-background-color--selected` | The cell background color when selected
`--px-data-table-cell-background-color--edit` | The cell background color when in edit mode
`--px-data-table-background-color-striped--even` | The background color of a striped cell (even)
`--px-data-table-cell-text-color--selected` | The cell text color when selected
`--px-data-table-cell-text-color-validation--failed` | The cell text color when validation fails
`--px-data-table-cell-text-color--sorted` | The text color of a sorted column
`--px-data-table-cell-text-color--editing` | The text color of a cell in edit mode
`--px-data-table-results-text-color--none` | The text color for the "no results" message
`--px-data-table-insertion-indicator-td-background-color` | The color of the insertion indicator for reordering
`--px-data-table-text-input-background-color--filter` | The background color of a filter input box
`--px-data-table-text-color--dragged` | The text color of a dragged item
`--px-data-table-text-color--hover` | The text color of a column header when hovered
`--px-data-table-highlight--high` | A highlight of value 'high'
`--px-data-table-highlight--medium` | A highlight of value 'medium'
`--px-data-table-highlight--low` | A highlight of value 'low'
`--px-data-table-padding-top` | The top padding for table cells
`--px-data-table-padding-bottom` | The bottom padding for table cells
`--px-data-table-padding-left` | The left padding for table cells
`--px-data-table-padding-right` | The right padding for table cells
@element px-data-table
@homepage index.html
@demo index.html
-->
<dom-module id="px-data-table">
<template>
<style include="px-data-table-styles"></style>
<div class="flex">
<aha-table
data-remote="{{dataRemote}}"
data="{{tableData}}"
enable-column-reorder="{{enableColumnReorder}}"
enable-column-resize="{{enableColumnResize}}"
filterable="{{filterable}}"
first-item-index="{{firstItemIndex}}"
hide-pagination-control="{{hidePaginationControl}}"
id="dataTable"
include-all-columns="{{includeAllColumns}}"
language="{{language}}"
meta="{{meta}}"
page-size-options="{{pageSizeOptions}}"
page-size="{{pageSize}}"
resources="{{resources}}"
selectable="{{selectable}}"
selected-rows="{{selectedRows}}"
show-column-chooser="{{showColumnChooser}}"
single-select="{{singleSelect}}"
sortable="{{sortable}}"
striped="{{striped}}"
table-cells="{{tableCells}}"
table-columns="{{tableColumns}}"
total-entries="{{totalEntries}}"
use-key-if-missing="{{useKeyIfMissing}}"
>
<content></content>
</aha-table>
</div>
</template>
</dom-module>
<script>
Polymer({
is: 'px-data-table',
behaviors: [
Polymer.AppLocalizeBehavior
],
properties: {
/**
* Data for the table to display.
*
* Expected data format is just a JSON array. Each object in the array represents a row in the table.
*
* Each item in an object will be displayed as a separate column, unless px-data-table-columns are defined to limit which columns are displayed.
* See also includeAllColumns.
*
* Expected format:
* [
* {
* "index": 0,
* "name": "Liz Grimes",
* "image": "https://s3.amazonaws.com/uifaces/faces/twitter/enda/73.jpg",
* "date": "Sun Aug 14 1994 03:27:03 GMT-0700 (PDT)"
* },
* {
* "index": 1,
* "name": "Frazier Lara",
* "image": "https://s3.amazonaws.com/uifaces/faces/twitter/guillogo/73.jpg",
* "date": "Tue May 24 1988 14:10:20 GMT-0700 (PDT)",
* }
* ]
*/
tableData: {
type: Array,
value: function() {
return [];
},
notify: true
},
/**
* If true, every other row in the table will appear with a background color to improve visual scanning.
*/
striped: {
type: Boolean,
value: false
},
/**
* If true, a row of filter inputs will appear under the column headings which allow the user to filter the table's contents.
* If columns are specified with px-data-table-column, they must also have a filterable property to enable filtering for that column.
* For custom filtering, see `filterFunctionName` in the px-data-table-column API using the dropdown at the top of this screen.
*/
filterable: {
type: Boolean,
value: false
},
/**
* If true, users can click on a column heading to sort table rows in a certain order (by default, alphabetically).
* If columns are specified with px-data-table-column, they must also have a sortable property to enable sorting for that column.
* For custom sorting, see `sortFunctionName` in the px-data-table-column API using the dropdown at the top of this screen.
*/
sortable: {
type: Boolean,
value: false
},
/**
* If true, the table will only appear with vertical borders.
*/
tableColumns: {
type: Boolean,
value: false
},
/**
* If true, the table will appear with both horizontal and vertical borders.
*/
tableCells: {
type: Boolean,
value: false
},
/**
* Use the selectable property if one or more rows within the table should be selectable. See also `singleSelect`.
*/
selectable: {
type: Boolean,
value: false
},
/**
* Use this property if only one row should be selectable at a time (radio button vs checkbox). The Select All checkbox will be hidden if `singleSelect` is true.
*/
singleSelect: {
type: Boolean,
value: false
},
/**
* Whether or not the table pagination controls should be hidden.
*/
hidePaginationControl: {
type: Boolean,
value: false
},
/**
* Property to set the the total number of entries in the table,
* assuming that dataRemote is true and the data provided is only
* for the visible page.
*
* Requires dataRemote="true" to take effect
*
* <px-data-table data-remote="true" page-size total-entries="100" first-item-index="0" table-data="{{data}}"></px-data-table>
*
* @default 10
*/
totalEntries: {
type: Number,
value: 10,
notify: true
},
/**
* Property to set the the remote index of the first item on this page,
* assuming that dataRemote is true and the data provided is only
* for the visible page.
*
* Requires dataRemote="true" to take effect
*
* If on page 2 with a page size of 10, then the first-item-index would be 11.
*
* <px-data-table data-remote="true" page-size total-entries="100" first-item-index="0" table-data="{{data}}"></px-data-table>
*
* @default 1
*/
firstItemIndex: {
type: Number,
value: 1,
notify: true
},
/**
* Property to set the the data paradigm.
*
* Local means all data is local.
* Remote means that only one page's worth of data is local.
*
* If this is false, then px-data-table expects all of the data to be provided to it.
*
* If this is true, then px-data-table will expect only one page's worth of data to be supplied.
* This will require other fields to be set, e.g. page-size, total-entries, and first-item-index
*
* <px-data-table data-remote="true" page-size total-entries="100" first-item-index="0" table-data="{{data}}"></px-data-table>
*
* @default false
*/
dataRemote: {
type: Boolean,
value: false
},
/**
* The default page size (number of visible rows) used in the pagination controls.
*
* Even in data-remote mode, page size may not match count of data provided.
* Page size could be 50, but only 40 items are provided.
*
* <px-data-table page-size="50" table-data="{{data}}"></px-data-table>
*
* @default 10
*/
pageSize: {
type: Number,
value: 10
},
/**
* Selected rows in the data table, setup for binding. This property is read only.
*/
selectedRows: {
type: Array,
value: function() {
return [];
},
notify: true
},
/**
* If true, a table column chooser will appear above the table, allowing the user to show and hide columns.
*/
showColumnChooser: {
type: Boolean,
value: false
},
/**
* If true, users can drag a column header from one location to another in order to reorder the columns.
*/
enableColumnReorder: {
type: Boolean,
value:false
},
/**
* Property to enable resizing of column headers through click and drag on
* the right border of the header.
* If there is no space available then resizing won't be possible (i.e all
* columns already to their minimum size, typically when the table can't
* be displayed entirely)
*/
enableColumnResize: {
type: Boolean,
value: false
},
/**
* By default, if you specify one or more `<px-data-table-column>` sub-component
* definitions, the table will only render those columns. By setting this boolean
* to true, the data table will include **all** columns of data found in table-data,
* with default settings **unless** you override these settings by including a
* `<px-data-table-column>` definition for that column. The `sortable` and `filterable`
* properties for each column will default to the current settings at the table level.
*/
includeAllColumns: {
type: Boolean,
value: false
},
/**
* Options displayed in the page size dropdown.
*/
pageSizeOptions: {
type: Array,
value: function() {
return [{"key":"1","val":"10"},
{"key":"2","val":"20"},
{"key":"3","val":"50"},
{"key":"4","val":"100"}];
}
},
/**
* A valid IETF language tag as a string that `app-localize-behavior` will
* use to localize this component.
*
* See https://github.com/PolymerElements/app-localize-behavior for API
* documentation and more information.
*/
language: {
type: String,
value: 'en'
},
useKeyIfMissing: {
type: Boolean,
value: true
},
/**
* A dictionary of strings used within the component for AppLocalizeBehavior
* to use, based on the selected `language` property.
*/
resources: {
type: Object,
value: function() {
return {
'en': {
"Selected": "Selected",
"of": "of",
"Show/Hide Column": "Show/Hide Column",
"Filter": "Filter",
"Rows per page": "Rows per page",
"No Results": "No Results"
}
}
}
}
},
/**
* Fired when a cell is clicked in the table. If the cell is not editable or of type 'dropdown',
* `px-row-click` will also be fired. Cell information is stored in `evt.detail`.
*
* @event px-cell-click
*/
/**
* Fired when table row is clicked (and selected or unselected, if selectable is true).
* Row information is stored in `evt.detail.row`:
* ```
* document.getElementById("mytable").addEventListener("px-row-click", function(e) {
* var clickedRow = e.detail.row;
* console.log("Row clicked: ", clickedRow);
* });
* ```
* @event px-row-click
*/
/**
* Fired when the select all button is clicked (and all rows are then selected or unselected).
* Row information is stored in `evt.detail`:
* ```
* document.getElementById("mytable").addEventListener("px-select-all-click", function(e) {
* var allSelectedRows = e.detail;
* console.log("Select/unselect all: ", allSelectedRows);
* });
* ```
* @event px-select-all-click
*/
// ------------------------------
// Remote Data Source Events
// ------------------------------
/**
* Fired when the data table initializes
* Sends out initialization information (such as suggested page size based on available space)
* Only fired if dataRemote==true
*
* Information is stored in `evt.detail`:
* ```
* document.getElementById("mytable").addEventListener("px-data-table-init", function(e) {
* var data = e.detail;
* console.log("Intended page: ", data);
* });
* // ==> {pageSize:10}
* ```
* @event px-data-table-init
*/
/**
* Fired when the user interaction indicates an intention to change the page
* Only fired if dataRemote==true
*
* Information is stored in `evt.detail`:
* ```
* document.getElementById("mytable").addEventListener("px-page-change-intent", function(e) {
* var data = e.detail;
* console.log("Intended page: ", data);
* });
* ```
* @event px-page-change-intent
*/
/**
* Fired when the user interaction indicates an intention to change the page size
* Only fired if dataRemote==true
*
* Information is stored in `evt.detail`:
* ```
* document.getElementById("mytable").addEventListener("px-page-size-change-intent", function(e) {
* var data = e.detail;
* console.log("Intended page size: ", data);
* });
* ```
* @event px-page-size-change-intent
*/
/**
* Fired when the user interaction indicates an intention to change the filter
* Captures filter data for all filtered columns
* Only fired if dataRemote==true
*
* Information is stored in `evt.detail`:
* ```
* document.getElementById("mytable").addEventListener("px-filter-change-intent", function(e) {
* var data = e.detail;
* console.log("Intended filters: ", JSON.parse(data));
* });
* // ==> [{name:'columnA',userEntry:'asdf'},{name:'columnB',userEntry:'qwert'}]
* ```
* @event px-filter-change-intent
*/
/**
* Fired when the user interaction indicates an intention to change the sort
* Captures sort data for all sorted columns (currently only single sort allowed through UI)
* Only fired if dataRemote==true
*
* Information is stored in `evt.detail`:
* ```
* document.getElementById("mytable").addEventListener("px-sort-change-intent", function(e) {
* var data = e.detail;
* console.log("Intended sort: ", JSON.parse(data));
* });
* // ==> [{name:'columnA',direction:'ascending'}] or [{name:'columnB',direction:'descending'}]
* ```
* @event px-sort-change-intent
*/
});
</script>