Skip to content

Commit e9a8e85

Browse files
authored
feat(forms): new b-form-datalist helper component (#2899)
1 parent 9d4408d commit e9a8e85

File tree

6 files changed

+130
-1
lines changed

6 files changed

+130
-1
lines changed

src/components/form-input/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,10 @@ chosen, or new values to be entered.
448448
<!-- b-form-input-datalist.vue -->
449449
```
450450

451+
BootstrapVue provides the form helper component
452+
[`<b-form-datalist>`](/docs/components/form/#datalist-helper) for quickly creating a `<datalist>`
453+
from an array of options.
454+
451455
**Notes:**
452456

453457
- Datalists work in conjunction with the browser's built in auto-complete, displaying datalist

src/components/form/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ See also:
177177
- `<b-form-text>` Help text blocks for inputs
178178
- `<b-form-invalid-feedback>` Invalid feedback text blocks for input `invalid` states
179179
- `<b-form-valid-feedback>` Valid feedback text blocks for input `valid` states
180+
- `<b-form-datalist>` Create `<datalist>` for use with `<b-form-input>` or plain `<input>`
180181

181182
See also: [`<b-form-group>`](/docs/components/form-group) Form input wrapper to generate form-groups
182183
that support labels, help text and feedback
@@ -262,6 +263,41 @@ or the `force-show` prop to display the feedback.
262263
<!-- form-feedback-example.vue -->
263264
```
264265

266+
### Datalist helper
267+
268+
For broswers that support
269+
[`<datalist>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist) elements,
270+
the `<b-form-datalist>` helper component will allow you to quickly create a `<datalist>` and
271+
child `<option>` elements via an array passed to the `options` prop.
272+
273+
```html
274+
<template>
275+
<label for="input-with-list">Input with datalist</label>
276+
<b-form-input list="input-list" id="input-with-list"></b-form-input>
277+
<b-form-datalist id="input-list" :options="options"></b-form-datalist>
278+
</template>
279+
280+
<script>
281+
export default {
282+
data() {
283+
return {
284+
options: ['Apple', 'Banana', 'Grape', 'Kiwi', 'Orange']
285+
}
286+
}
287+
}
288+
</script>
289+
290+
<!-- form-datalist-example.vue -->
291+
```
292+
293+
`<b-form-datalist>` is also available via the shorter alias of `<b-datalist>`.
294+
295+
See also:
296+
297+
- [`<b-form-input> datalist`](/docs/components/form-input#datalist-support) for datalist usage.
298+
- [`<b-form-select> options`](/docs/components/form-select#options-property) for more information on
299+
the `options` array format.
300+
265301
## Validation
266302

267303
Disable browser native HTML5 validation by setting the `novalidate` prop to true on `<b-form>`.

src/components/form/form-datalist.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import formOptionsMixin from '../../mixins/form-options'
2+
import { htmlOrText } from '../../utils/html'
3+
4+
// @vue/component
5+
export default {
6+
name: 'BFormDatalist',
7+
mixins: [formOptionsMixin],
8+
props: {
9+
id: {
10+
type: String,
11+
default: null,
12+
required: true
13+
}
14+
},
15+
render(h) {
16+
const options = this.formOptions.map((option, index) => {
17+
return h('option', {
18+
key: `option_${index}_opt`,
19+
attrs: { disabled: option.disabled },
20+
domProps: { ...htmlOrText(option.html, option.text), value: option.value }
21+
})
22+
})
23+
return h('datalist', { attrs: { id: this.id } }, [options, this.$slots.default])
24+
}
25+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import Datalist from './form-datalist'
2+
import { mount } from '@vue/test-utils'
3+
4+
describe('form-datalist', () => {
5+
it('has root element datalist', async () => {
6+
const wrapper = mount(Datalist, {
7+
propsData: {
8+
id: 'testlist'
9+
}
10+
})
11+
expect(wrapper.is('datalist')).toBe(true)
12+
13+
wrapper.destroy()
14+
})
15+
16+
it('has user supplied ID', async () => {
17+
const wrapper = mount(Datalist, {
18+
propsData: {
19+
id: 'testlist'
20+
}
21+
})
22+
expect(wrapper.attributes('id')).toBe('testlist')
23+
24+
wrapper.destroy()
25+
})
26+
27+
it('has no oprion elements by default', async () => {
28+
const wrapper = mount(Datalist, {
29+
propsData: {
30+
id: 'testlist'
31+
}
32+
})
33+
expect(wrapper.findAll('option').length).toBe(0)
34+
35+
wrapper.destroy()
36+
})
37+
38+
it('has options when options set', async () => {
39+
const wrapper = mount(Datalist, {
40+
propsData: {
41+
id: 'testlist',
42+
options: ['one', 'two']
43+
}
44+
})
45+
const $options = wrapper.findAll('option')
46+
47+
expect($options.length).toBe(2)
48+
49+
expect($options.at(0).text()).toBe('one')
50+
expect($options.at(1).text()).toBe('two')
51+
52+
expect($options.at(0).attributes('value')).toBe('one')
53+
expect($options.at(1).attributes('value')).toBe('two')
54+
55+
wrapper.destroy()
56+
})
57+
})

src/components/form/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import BForm from './form'
2+
import BFormDatalist from './form-datalist'
23
import BFormRow from './form-row'
34
import BFormText from './form-text'
45
import BFormInvalidFeedback from './form-invalid-feedback'
@@ -7,6 +8,8 @@ import { registerComponents } from '../../utils/plugins'
78

89
const components = {
910
BForm,
11+
BFormDatalist,
12+
BDatalist: BFormDatalist,
1013
BFormRow,
1114
BFormText,
1215
BFormInvalidFeedback,

src/components/form/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@
2323
"BFormText",
2424
"BFormInvalidFeedback",
2525
"BFormValidFeedback",
26-
"BFormRow"
26+
"BFormRow",
27+
{
28+
"component": "BFormDatalist",
29+
"aliases": ["BDatalist"]
30+
}
2731
]
2832
}
2933
}

0 commit comments

Comments
 (0)