Skip to content
Permalink
Browse files

feat(b-table, b-table-lite): switch slot name syntax to use round bra…

…ckets instead of square brackets (#3986)
  • Loading branch information...
tmorehouse committed Aug 30, 2019
1 parent 487c592 commit fca7bd54c17f42ee5361cf5bf6395f3bb205c333
@@ -50,13 +50,13 @@
bordered
striped
>
<template v-slot:cell[prop]="{ value, item }">
<template v-slot:cell(prop)="{ value, item }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code>
<b-badge v-if="item.required" variant="info">Required</b-badge>
<b-badge v-else-if="item.deprecated" variant="danger">Deprecated</b-badge>
<b-badge v-else-if="item.deprecation" variant="warning">Deprecation</b-badge>
</template>
<template v-slot:cell[defaultValue]="{ value }">
<template v-slot:cell(defaultValue)="{ value }">
<code v-if="value" class="notranslate" translate="no">{{ value }}</code>
</template>
<template v-slot:row-details="{ item }">
@@ -82,10 +82,10 @@
bordered
striped
>
<template v-slot:cell[prop]="{ value }">
<template v-slot:cell(prop)="{ value }">
<code class="notranslate" translate="no">{{ kebabCase(value) }}</code>
</template>
<template v-slot:cell[event]="{ value }">
<template v-slot:cell(event)="{ value }">
<code class="notranslate" translate="no">{{ value }}</code>
</template>
</b-table>
@@ -105,7 +105,7 @@
bordered
striped
>
<template v-slot:cell[name]="{ value }">
<template v-slot:cell(name)="{ value }">
<code class="text-nowrap nostranslate" translate="no">{{ value }}</code>
</template>
</b-table>
@@ -124,10 +124,10 @@
bordered
striped
>
<template v-slot:cell[event]="{ value }">
<template v-slot:cell(event)="{ value }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code>
</template>
<template v-slot:cell[args]="{ value, item }">
<template v-slot:cell(args)="{ value, item }">
<p
v-for="arg in value"
:key="`event-${item.event}-${arg.arg ? arg.arg : 'none'}`"
@@ -159,10 +159,10 @@
bordered
striped
>
<template v-slot:cell[event]="{ value }">
<template v-slot:cell(event)="{ value }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code>
</template>
<template v-slot:cell[args]="{ value, item }">
<template v-slot:cell(args)="{ value, item }">
<p
v-for="arg in value"
:key="`event-${item.event}-${arg.arg ? arg.arg : 'none'}`"
@@ -22,13 +22,13 @@
bordered
striped
>
<template v-slot:cell[component]="{ value }">
<template v-slot:cell(component)="{ value }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code>
</template>
<template v-slot:cell[namedExport]="{ value }">
<template v-slot:cell(namedExport)="{ value }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code>
</template>
<template v-slot:cell[importPath]="{ value }">
<template v-slot:cell(importPath)="{ value }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code>
</template>
</b-table>
@@ -57,13 +57,13 @@
bordered
striped
>
<template v-slot:cell[directive]="{ value }">
<template v-slot:cell(directive)="{ value }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code>
</template>
<template v-slot:cell[namedExport]="{ value }">
<template v-slot:cell(namedExport)="{ value }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code>
</template>
<template v-slot:cell[importPath]="{ value }">
<template v-slot:cell(importPath)="{ value }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code>
</template>
</b-table>
@@ -97,10 +97,10 @@
bordered
striped
>
<template v-slot:cell[namedExport]="{ value }">
<template v-slot:cell(namedExport)="{ value }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code>
</template>
<template v-slot:cell[importPath]="{ value }">
<template v-slot:cell(importPath)="{ value }">
<code class="text-nowrap notranslate" translate="no">{{ value }}</code>
</template>
</b-table>
@@ -806,9 +806,9 @@ Scoped field slots give you greater control over how the record data appears. Yo
slots to provided custom rendering for a particular field. If you want to add an extra field which
does not exist in the records, just add it to the [`fields`](#fields-column-definitions) array, and
then reference the field(s) in the scoped slot(s). Scoped field slots use the following naming
syntax: `'cell[' + field key + ']'`.
syntax: `'cell(' + field key + ')'`.

You can use the default _fall-back_ scoped slot `'cell[]'` to format any cells that do not have an
You can use the default _fall-back_ scoped slot `'cell()'` to format any cells that do not have an
explicit scoped slot provided.

**Example: Custom data rendering with scoped slots**
@@ -818,22 +818,22 @@ explicit scoped slot provided.
<div>
<b-table small :fields="fields" :items="items">
<!-- A virtual column -->
<template v-slot:cell[index]="data">
<template v-slot:cell(index)="data">
{{ data.index + 1 }}
</template>

<!-- A custom formatted column -->
<template v-slot:cell[name]="data">
<b>{{ data.value.last }}</b>, {{ data.value.first }}
<template v-slot:cell(name)="data">
<b class="text-info">{{ data.value.last.toUpperCase() }}</b>, <b>{{ data.value.first }}<b>
</template>

<!-- A virtual composite column -->
<template v-slot:cell[nameage]="data">
<template v-slot:cell(nameage)="data">
{{ data.item.name.first }} is {{ data.item.age }} years old
</template>

<!-- Optional default data cell scoped slot -->
<template v-slot:cell[]="data">
<template v-slot:cell()="data">
<i>{{ data.value }}</i>
</template>
</b-table>
@@ -903,7 +903,7 @@ scoped field slot.
<template>
<div>
<b-table :items="items">
<template v-slot:cell[html]="data">
<template v-slot:cell(html)="data">
<span v-html="data.value"></span>
</template>
</b-table>
@@ -954,7 +954,7 @@ formatted value as a string (HTML strings are not supported)
<template>
<div>
<b-table :fields="fields" :items="items">
<template v-slot:cell[name]="data">
<template v-slot:cell(name)="data">
<!-- `data.value` is the value after formatted by the Formatter -->
<a :href="`#${data.value.replace(/[^a-z]+/i,'-').toLowerCase()}`">{{ data.value }}</a>
</template>
@@ -1017,34 +1017,34 @@ It is also possible to provide custom rendering for the tables `thead` and `tfoo
default the table footer is not rendered unless `foot-clone` is set to `true`.

Scoped slots for the header and footer cells uses a special naming convention of
`'head[<fieldkey>]'` and `'foot[<fieldkey>]'` respectively. if a `'foot[...]'` slot for a field is
not provided, but a `'head[...]'` slot is provided, then the footer will use the `'head[...]'` slot
`'head(<fieldkey>)'` and `'foot(<fieldkey>)'` respectively. if a `'foot(...)'` slot for a field is
not provided, but a `'head(...)'` slot is provided, then the footer will use the `'head(...)'` slot
content.

You can use a default _fall-back_ scoped slot `'head[]'` or `'foot[]'` to format any header or
You can use a default _fall-back_ scoped slot `'head()'` or `'foot()'` to format any header or
footer cells that do not have an explicit scoped slot provided.

```html
<template>
<div>
<b-table :fields="fields" :items="items" foot-clone>
<!-- A custom formatted data column cell -->
<template v-slot:cell[name]="data">
<template v-slot:cell(name)="data">
{{ data.value.first }} {{ data.value.last }}
</template>

<!-- A custom formatted header cell for field 'name' -->
<template v-slot:head[name]="data">
<span class="text-info">{{ data.label }}</b>
<template v-slot:head(name)="data">
<span class="text-info">{{ data.label.toUpperCase() }}</b>
</template>

<!-- A custom formatted footer cell for field 'name' -->
<template v-slot:foot[name]="data">
<template v-slot:foot(name)="data">
<span class="text-danger">{{ data.label }}</span>
</template>

<!-- Default fall-back custom formatted footer cell -->
<template v-slot:foot[]="data">
<template v-slot:foot()="data">
<i>{{ data.label }}</i>
</template>
</b-table>
@@ -1088,7 +1088,7 @@ properties:
| `selectAllRows` | Method | Select all rows (applicable if the table is in [`selectable`](#row-select-support) mode |
| `clearSelected` | Method | Unselect all rows (applicable if the table is in [`selectable`](#row-select-support) mode |

When placing inputs, buttons, selects or links within a `HEAD[...]` or `FOOT[...]` slot, note that
When placing inputs, buttons, selects or links within a `head(...)` or `foot(...)` slot, note that
`head-clicked` event will not be emitted when the input, select, textarea is clicked (unless they
are disabled). `head-clicked` will never be emitted when clicking on links or buttons inside the
scoped slots (even when disabled)
@@ -1117,7 +1117,7 @@ rather than native browser table child elements.
>
<template v-slot:thead-top="data">
<b-tr>
<b-td colspan="2">&nbsp;</b-td>
<b-th colspan="2"><span class="sr-only">Name and ID</span></b-th>
<b-th variant="secondary">Type 1</b-th>
<b-th variant="primary" colspan="3">Type 2</b-th>
<b-th variant="danger">Type 3</b-th>
@@ -1250,11 +1250,11 @@ available horizontal space.
- Bootstrap v4 uses the CSS style `border-collapse: collapsed` on table elements. This prevents the
borders on the sticky header from "sticking" to the header, and hence the borders will scroll when
the body scrolls. To get around this issue, create some custom CSS that targets
`table.table.b-table`, which sets they styles `border-collapse: collapsed; border-spacing: 0px;`
`table.table.b-table`, which sets they styles `border-collapse: separate; border-spacing: 0px;`
(note that this may cause double borders when using features such as `bordered`, etc).
- The sticky header feature uses CSS style `position: sticky` to position the headings.
- Internet Explorer does not support `position: sticky`, hence for IE11 the table headings will
scroll with the table body.
- The sticky header feature uses CSS style `position: sticky` to position the headings. Internet
Explorer does not support `position: sticky`, hence for IE11 the table headings will scroll with
the table body.

### Sticky columns

@@ -1272,10 +1272,10 @@ set.
<b-form-checkbox v-model="stickyHeader" class="mb-2">Sticky header</b-form-checkbox>
<b-table :sticky-header="stickyHeader" responsive :items="items" :fields="fields">
<!-- We are using utility class `text-nowrap` to help illustrate horizontal scrolling -->
<template v-slot:head[id]="scope">
<template v-slot:head(id)="scope">
<div class="text-nowrap">Row ID</div>
</template>
<template v-slot:head[]="scope">
<template v-slot:head()="scope">
<div class="text-nowrap">
Heading {{ scope.label }}
</div>
@@ -1379,7 +1379,7 @@ initially showing.
<template>
<div>
<b-table :items="items" :fields="fields" striped responsive="sm">
<template v-slot:cell[show_details]="row">
<template v-slot:cell(show_details)="row">
<b-button size="sm" @click="row.toggleDetails" class="mr-2">
{{ row.detailsShowing ? 'Hide' : 'Show'}} Details
</b-button>
@@ -1486,7 +1486,7 @@ Programmatic selection notes:
responsive="sm"
>
<!-- Example scoped slot for select state illustrative purposes -->
<template v-slot:cell[selected]="{ rowSelected }">
<template v-slot:cell(selected)="{ rowSelected }">
<template v-if="rowSelected">
<span aria-hidden="true">&check;</span>
<span class="sr-only">Selected</span>
@@ -2652,8 +2652,8 @@ helper components are as follows:

These components are optimized to handle converting variants to the appropriate classes (such as
handling table `dark` mode), and automatically applying certain accessibility attributes (i.e.
`role`s and `scope`s). It can generate the stacked table and sticky-header requirements. Components
`<b-table>` and `<b-table-lite>` use these helper components internally.
`role`s and `scope`s). They also can generate the stacked table, and sticky header and column,
markup. Components `<b-table>` and `<b-table-lite>` use these helper components internally.

In the [Simple tables](#simple-tables) example, we are using the helper components `<b-thead>`,
`<b-tbody>`, `<b-tr>`, `<b-th>`, `<b-tr>` and `<b-tfoot>`. While you can use regular table child
@@ -2697,9 +2697,10 @@ trigger your click on cells or rows (required for accessibility for keyboard-onl
### Heading accessibility

When a column (field) is sortable (`<b-table>` only) or there is a `head-clicked` listener
registered, the header (and footer) `<th>` cells will be placed into the document tab sequence (via
`tabindex="0"`) for accessibility by keyboard-only and screen reader users, so that the user may
trigger a click (by pressing <kbd>ENTER</kbd> on the header cells.
registered (`<b-table>` and `<b-table-lite>`), the header (and footer) `<th>` cells will be placed
into the document tab sequence (via `tabindex="0"`) for accessibility by keyboard-only and screen
reader users, so that the user may trigger a click (by pressing <kbd>ENTER</kbd> on the header
cells.

### Data row accessibility

@@ -2881,11 +2882,11 @@ your app handles the various inconsistencies with events.
:sort-direction="sortDirection"
@filtered="onFiltered"
>
<template v-slot:cell[name]="row">
<template v-slot:cell(name)="row">
{{ row.value.first }} {{ row.value.last }}
</template>

<template v-slot:cell[actions]="row">
<template v-slot:cell(actions)="row">
<b-button size="sm" @click="info(row.item, row.index, $event.target)" class="mr-1">
Info modal
</b-button>
@@ -203,7 +203,9 @@ export default {
// The new `v-slot` syntax doesn't like a slot name starting with
// a square bracket and if using in-document HTML templates, the
// v-slot attributes are lower-cased by the browser.
const slotNames = [`cell[${key}]`, `cell[${key.toLowerCase()}]`, 'cell[]']
// Switched to round bracket syntax to prevent confusion with
// dynamic slot name syntax.
const slotNames = [`cell(${key})`, `cell(${key.toLowerCase()})`, 'cell()']
let $childNodes = this.hasNormalizedSlot(slotNames)
? this.normalizeSlot(slotNames, slotScope)
: toString(formatted)
@@ -106,13 +106,15 @@ export default {
// Handle edge case where in-document templates are used with new
// `v-slot:name` syntax where the browser lower-cases the v-slot's
// name (attributes become lower cased when parsed by the browser)
let slotNames = [`head[${field.key}]`, `head[${field.key.toLowerCase()}]`, 'head[]']
// We have replaced the square bracket syntax with round brackets
// to prevent confusion with dynamic slot names
let slotNames = [`head(${field.key})`, `head(${field.key.toLowerCase()})`, 'head()']
if (isFoot) {
// Footer will fallback to header slot names
slotNames = [
`foot[${field.key}]`,
`foot[${field.key.toLowerCase()}]`,
'foot[]',
`foot(${field.key})`,
`foot(${field.key.toLowerCase()})`,
'foot()',
...slotNames
]
}
@@ -187,7 +187,7 @@ describe('table > row details', () => {
scopeDetails = scope
return 'foobar'
},
'cell[a]': function(scope) {
'cell(a)': function(scope) {
scopeField = scope
return 'AAA'
}
@@ -333,13 +333,13 @@ describe('table > tbody row events', () => {
},
slots: {
// In Vue 2.6x, slots get translated into scopedSlots
'cell[a]': '<button id="a">button</button>',
'cell[b]': '<input id="b">',
'cell[c]': '<a href="#" id="c">link</a>',
'cell[d]':
'cell(a)': '<button id="a">button</button>',
'cell(b)': '<input id="b">',
'cell(c)': '<a href="#" id="c">link</a>',
'cell(d)':
'<div class="dropdown-menu"><div id="d" class="dropdown-item">dropdown</div></div>',
'cell[e]': '<label for="e">label</label><input id="e">',
'cell[f]': '<label class="f-label"><input id="e"></label>'
'cell(e)': '<label for="e">label</label><input id="e">',
'cell(f)': '<label class="f-label"><input id="e"></label>'
},
listeners: {
// Row-clicked will only occur if there is a registered listener
@@ -106,10 +106,10 @@ describe('table > tfoot events', () => {
},
slots: {
// In Vue 2.6x, slots get translated into scopedSlots
'foot[a]': '<button id="a">button</button>',
'foot[b]': '<input id="b">',
'foot(a)': '<button id="a">button</button>',
'foot(b)': '<input id="b">',
// Will use `head` slot if foot slot not defined
'head[c]': '<a href="#" id="c">link</a>'
'head(c)': '<a href="#" id="c">link</a>'
}
})
expect(wrapper).toBeDefined()

0 comments on commit fca7bd5

Please sign in to comment.
You can’t perform that action at this time.