Skip to content

Commit 9da94a6

Browse files
authored
feat(table): add field data formatter prop (bootstrap-vue#739)
* 1. Add new prop to field - formatter, to allow custom formatting via callback function 2. Add api-url prop to pass to callback item provider function 3. Move sortBy and sortDesc props to Props instead Data, to allow define custom sorting on mount 4. Some refactor 5. edit (Doc) Add formatter using info and examples
1 parent 919344b commit 9da94a6

File tree

5 files changed

+158
-114
lines changed

5 files changed

+158
-114
lines changed

.eslintrc.js

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,6 @@ module.exports = {
7777
'eqeqeq': 'off',
7878
'func-call-spacing': 'error',
7979
'func-name-matching': 'error',
80-
'func-names': [
81-
'error',
82-
'never'
83-
],
8480
'func-style': 'error',
8581
'generator-star-spacing': 'error',
8682
'global-require': 'off',
@@ -109,7 +105,6 @@ module.exports = {
109105
'lines-around-directive': 'error',
110106
'max-depth': 'error',
111107
'max-len': 'off',
112-
'max-lines': 'error',
113108
'max-nested-callbacks': 'error',
114109
'max-params': ['error', 4],
115110
'max-statements': 'off',
@@ -203,7 +198,6 @@ module.exports = {
203198
'no-trailing-spaces': 'off',
204199
'no-undef-init': 'error',
205200
'no-undefined': 'warn',
206-
'no-underscore-dangle': 'error',
207201
'no-unmodified-loop-condition': 'error',
208202
'no-unneeded-ternary': 'error',
209203
'no-unused-expressions': ['error', {'allowShortCircuit': true, 'allowTernary': true}],
@@ -242,8 +236,6 @@ module.exports = {
242236
'prefer-numeric-literals': 'error',
243237
'prefer-promise-reject-errors': 'error',
244238
'prefer-reflect': 'off',
245-
'prefer-rest-params': 'error',
246-
'prefer-spread': 'error',
247239
'prefer-template': 'off',
248240
'quote-props': 'off',
249241
'quotes': 'off',
@@ -285,4 +277,4 @@ module.exports = {
285277
'never'
286278
]
287279
}
288-
};
280+
};

docs/components/table/README.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ Example format:
127127
{
128128
name: {
129129
label: 'Person Full name',
130-
sortable: true
130+
sortable: true,
131+
formatter: 'personFullName'
131132
},
132133
age: {
133134
label: 'Person age',
@@ -147,6 +148,7 @@ Supported field properties:
147148
| `thClass` | String or Array | Class name (or array of class names) to add to header/footer `<th>` cell
148149
| `tdClass` | String or Array | Class name (or array of class names) to add to data `<td>` cells in the column
149150
| `thStyle` | Object | JavaScript object representing CSS styles you would like to apply to the table field `<th>`
151+
| `formatter` | String or Function | A formatter callback function, can be used instead of slots for real table fields (i.e. fields, that have corresponding data at items array)
150152

151153
Notes:
152154
- Field properties, if not present, default to null unless otherwise stated above.
@@ -156,6 +158,7 @@ Notes:
156158
in the Vue.js guide.
157159
- Any additional properties added to the field objects will be left intact - so you can access
158160
them via the named scoped slots for custom data, header, and footer rendering.
161+
- by design, slots and formatter are **mutually exclusive**. Ie. if formatter defined at field props, then slot will not be used even if it defined for this field.
159162

160163
### Items (record data)
161164
`items` are real table data record objects in array format. Example format:
@@ -223,8 +226,10 @@ See the **"Using Items Provider functions"** section below for more details.
223226

224227

225228
### Custom Data Rendering
226-
Custom rendering for each data field in a row is possible using
227-
[scoped slots](http://vuejs.org/v2/guide/components.html#Scoped-Slots).
229+
Custom rendering for each data field in a row is possible using either
230+
[scoped slots](http://vuejs.org/v2/guide/components.html#Scoped-Slots) or formatter callback function.
231+
232+
####Slots
228233
If you want to add an extra field which does not exist in the records,
229234
just add it to the `fields` array. Example:
230235

@@ -310,6 +315,29 @@ event:
310315
<b-btn size="sm" @click.stop="details(cell.item,cell.index,$event.target)">Details</b-btn>
311316
</template>
312317
```
318+
#### Formatter callback
319+
320+
Other option to make custom field output is to use formatter callback function.
321+
To enable this field's property `formatter` is used. Value of this property may be
322+
String or function reference. In case of String value, function must be defined at parent component's methods,
323+
to provide formatter as `Function`, it must be declared at global scope (window or as global mixin at Vue).
324+
325+
Example:
326+
```js
327+
{
328+
name: {
329+
label: 'Person Full name',
330+
sortable: true,
331+
formatter: 'personFullName'
332+
},
333+
age: {
334+
label: 'Person age',
335+
sortable: false,
336+
fomatter: personAge
337+
}
338+
}
339+
```
340+
313341

314342
### Header/Footer Custom Rendering
315343
It is also possible to provide custom rendering for the tables `thead` and

examples/table/demo.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,5 +124,4 @@ <h2>Provider Test Table</h2>
124124
<b-btn size="sm" @click.stop="details(data.item)">Details</b-btn>
125125
</template>
126126
</b-table>
127-
128127
</div>

examples/table/demo.js

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ window.app = new Vue({
88
},
99
age: {
1010
label: 'Person age',
11-
sortable: true
11+
sortable: true,
12+
formatter: 'formatAge'
1213
},
1314
isActive: {
1415
label: 'is Active'
@@ -79,13 +80,14 @@ window.app = new Vue({
7980
},
8081
computed: {
8182
provider() {
82-
// we are usig provider wrappers here to trigger a reload
83-
if (this.providerType === 'promise') {
84-
return this._promiseProvider;
85-
} else if (this.providerType === 'callback') {
86-
return this._callbackProvider;
87-
} else {
88-
return this._arrayProvider;
83+
// we are using provider wrappers here to trigger a reload
84+
switch (this.providerType){
85+
case 'promise':
86+
return this._promiseProvider;
87+
case 'callback':
88+
return this._callbackProvider;
89+
default:
90+
return this._arrayProvider;
8991
}
9092
}
9193
},
@@ -105,19 +107,22 @@ window.app = new Vue({
105107
},
106108
_provider(ctx, cb) {
107109
const items = this.items.slice();
108-
if (this.providerType === 'callback') {
109-
setTimeout(() => {
110-
cb(items);
111-
}, 1)
112-
return;
113-
} else if (this.providerType === 'promise') {
114-
const p = new Promise(resolve => setTimeout(resolve, 1));
115-
return p.then(() => {
116-
return items;
117-
});
118-
} else {
119-
return items;
110+
111+
switch (this.providerType){
112+
case 'callback':
113+
setTimeout(() => {cb(items);}, 1)
114+
return;
115+
case 'promise':
116+
const p = new Promise(resolve => setTimeout(resolve, 1));
117+
return p.then(() => {
118+
return items;
119+
});
120+
default:
121+
return items;
120122
}
123+
},
124+
formatAge(value){
125+
return `${value} years old`;
121126
}
122127
}
123128
});

0 commit comments

Comments
 (0)