Skip to content

Commit

Permalink
feat(b-form-select): add group/tree support and dedicated option and …
Browse files Browse the repository at this point in the history
…option-group components (closes #3222) (#4267)

* feat(b-form-select): add group/tree support and dedicated option and option-group components

* Improve option property handling

* Update package.json

* Nested `<optgroup>`'s is invalid HTML...

* remove duplicate import

* Update index.js

* Update mixin-options.js

* Update form-datalist.spec.js

* Create form-select-option.spec.js

* Update form-options.js

* Create form-select-option-group.spec.js

* Update form-select.spec.js

* Improve warnings

* Update form-select.spec.js

* Update form-select.spec.js

* Update README.md

* Update README.md

* Update package.json

* Update _slug.js

* Update componentdoc.vue

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md
  • Loading branch information
jacobmllr95 authored Nov 18, 2019
1 parent f3f5279 commit f1ed017
Show file tree
Hide file tree
Showing 27 changed files with 875 additions and 115 deletions.
5 changes: 5 additions & 0 deletions docs/components/componentdoc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<anchored-heading :id="`comp-ref-${componentName}`" level="3">
<code class="notranslate bigger" translate="no">{{ tag }}</code>
</anchored-heading>
<b-badge v-if="version" variant="success">v{{ version }}+</b-badge>
<b-badge
v-if="componentFunctional"
variant="secondary"
Expand Down Expand Up @@ -340,6 +341,10 @@ export default {
aliases: {
type: Array,
default: () => []
},
version: {
type: String,
default: null
}
},
computed: {
Expand Down
4 changes: 2 additions & 2 deletions docs/pages/docs/components/_slug.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ export default {
h(AnchoredHeading, { props: { id: 'component-reference' } }, 'Component reference'),
// Component reference information
...this.meta.components.map(
({ component, events, rootEventListeners, slots, aliases, props: propsMeta }) =>
({ component, events, rootEventListeners, slots, aliases, props: propsMeta, version }) =>
h(Componentdoc, {
props: { component, events, rootEventListeners, slots, aliases, propsMeta }
props: { component, events, rootEventListeners, slots, aliases, propsMeta, version }
})
),
// Component importing information
Expand Down
120 changes: 118 additions & 2 deletions src/components/form-checkbox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,124 @@ named slot `first`.

## Checkbox group options array

Please see the [`<b-form-select>` `options` prop](/docs/components/form-select#options-property)
docs for details on the formats and helper props associated with `options`.
`options` can be an array of strings or objects. Available fields:

- **`value`** The selected value which will be set on `v-model`
- **`disabled`** Disables item for selection
- **`text`** Display text, or **`html`** Display basic inline html

`value` can be a string, number, or simple object. Avoid using complex types in values.

If both `html` and `text` are provided, `html` will take precedence. Only basic/native HTML is
supported in the `html` field (components will not work). Note that not all browsers will render
inline html (i.e. `<i>`, `<strong>`, etc) inside `<option>` elements of a `<select>`.

<p class="alert alert-danger">
<strong>Be cautious</strong> of placing user supplied content in the <code>html</code> field,
as it may make you vulnerable to
<a class="alert-link" href="https://en.wikipedia.org/wiki/Cross-site_scripting">
<abbr title="Cross Site Scripting Attacks">XSS attacks</abbr></a>, if you do not first
<a class="alert-link" href="https://en.wikipedia.org/wiki/HTML_sanitization">sanitize</a> the
user supplied string.
</p>

<!-- eslint-disable no-unused-vars -->

```js
const options = ['A', 'B', 'C', { text: 'D', value: { d: 1 }, disabled: true }, 'E', 'F']
```

If an array entry is a string, it will be used for both the generated `value` and `text` fields.

You can mix using strings and [objects](#options-as-an-array-of-objects) in the array.

Internally, BootstrapVue will convert the above array to the following array (the
[array of objects](#options-as-an-array-of-objects)) format:

<!-- eslint-disable no-unused-vars -->

```js
const options = [
{ text: 'A', value: 'A', disabled: false },
{ text: 'B', value: 'B', disabled: false },
{ text: 'C', value: 'C', disabled: false },
{ text: 'D', value: { d: 1 }, disabled: true },
{ text: 'E', value: 'E', disabled: false },
{ text: 'F', value: 'F', disabled: false }
]
```

### Options as an array of objects

<!-- eslint-disable no-unused-vars -->

```js
const options = [
{ text: 'Item 1', value: 'first' },
{ text: 'Item 2', value: 'second' },
{ html: '<b>Item</b> 3', value: 'third', disabled: true },
{ text: 'Item 4' },
{ text: 'Item 5', value: { foo: 'bar', baz: true } }
]
```

If `value` is missing, then `text` will be used as both the `value` and `text` fields. If you use
the `html` property, you **must** supply a `value` property.

Internally, BootstrapVue will convert the above array to the following array (the
[array of objects](#options-as-an-array-of-objects)) format:

<!-- eslint-disable no-unused-vars -->

```js
const options = [
{ text: 'Item 1', value: 'first', disabled: false },
{ text: 'Item 2', value: 'second', disabled: false },
{ html: '<b>Item</b> 3', value: 'third', disabled: true },
{ text: 'Item 4', value: 'Item 4', disabled: false },
{ text: 'Item 5', value: 'E', disabled: false }
]
```

### Changing the option field names

If you want to customize the field property names (for example using `name` field for display
`text`) you can easily change them by setting the `text-field`, `html-field`, `value-field`, and
`disabled-field` props to a string that contains the property name you would like to use:

```html
<template>
<div>
<b-form-checkbox-group
v-model="selected"
:options="options"
class="mb-3"
value-field="item"
text-field="name"
disabled-field="notEnabled"
></b-form-checkbox-group>
<div class="mt-3">Selected: <strong>{{ selected }}</strong></div>
</div>
</template>

<script>
export default {
data() {
return {
selected: [],
options: [
{ item: 'A', name: 'Option A' },
{ item: 'B', name: 'Option B' },
{ item: 'D', name: 'Option C', notEnabled: true },
{ item: { d: 1 }, name: 'Option D' }
]
}
}
}
</script>

<!-- b-form-checkbox-group-options-fields.vue -->
```

## Inline and stacked checkboxes

Expand Down
7 changes: 4 additions & 3 deletions src/components/form-file/form-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import normalizeSlotMixin from '../../mixins/normalize-slot'

const NAME = 'BFormFile'

const VALUE_EMPTY_DEPRECATED_MSG =
'Setting "value"/"v-model" to an empty string for reset is deprecated. Set to "null" instead.'

// @vue/component
export const BFormFile = /*#__PURE__*/ Vue.extend({
name: NAME,
Expand All @@ -32,9 +35,7 @@ export const BFormFile = /*#__PURE__*/ Vue.extend({
validator: val => {
/* istanbul ignore next */
if (val === '') {
warn(
`${NAME} - setting value/v-model to an empty string for reset is deprecated. Set to 'null' instead`
)
warn(VALUE_EMPTY_DEPRECATED_MSG, NAME)
return true
}
return (
Expand Down
120 changes: 118 additions & 2 deletions src/components/form-radio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,124 @@ To have them appear _above_ the inputs generated by `options`, place them in the

## Radio group options array

Please see the [`<b-form-select>` `options` prop](/docs/components/form-select#options-property)
docs for details on the formats and helper props associated with `options`.
`options` can be an array of strings or objects. Available fields:

- **`value`** The selected value which will be set on `v-model`
- **`disabled`** Disables item for selection
- **`text`** Display text, or **`html`** Display basic inline html

`value` can be a string, number, or simple object. Avoid using complex types in values.

If both `html` and `text` are provided, `html` will take precedence. Only basic/native HTML is
supported in the `html` field (components will not work). Note that not all browsers will render
inline html (i.e. `<i>`, `<strong>`, etc) inside `<option>` elements of a `<select>`.

<p class="alert alert-danger">
<strong>Be cautious</strong> of placing user supplied content in the <code>html</code> field,
as it may make you vulnerable to
<a class="alert-link" href="https://en.wikipedia.org/wiki/Cross-site_scripting">
<abbr title="Cross Site Scripting Attacks">XSS attacks</abbr></a>, if you do not first
<a class="alert-link" href="https://en.wikipedia.org/wiki/HTML_sanitization">sanitize</a> the
user supplied string.
</p>

<!-- eslint-disable no-unused-vars -->

```js
const options = ['A', 'B', 'C', { text: 'D', value: { d: 1 }, disabled: true }, 'E', 'F']
```

If an array entry is a string, it will be used for both the generated `value` and `text` fields.

You can mix using strings and [objects](#options-as-an-array-of-objects) in the array.

Internally, BootstrapVue will convert the above array to the following array (the
[array of objects](#options-as-an-array-of-objects)) format:

<!-- eslint-disable no-unused-vars -->

```js
const options = [
{ text: 'A', value: 'A', disabled: false },
{ text: 'B', value: 'B', disabled: false },
{ text: 'C', value: 'C', disabled: false },
{ text: 'D', value: { d: 1 }, disabled: true },
{ text: 'E', value: 'E', disabled: false },
{ text: 'F', value: 'F', disabled: false }
]
```

### Options as an array of objects

<!-- eslint-disable no-unused-vars -->

```js
const options = [
{ text: 'Item 1', value: 'first' },
{ text: 'Item 2', value: 'second' },
{ html: '<b>Item</b> 3', value: 'third', disabled: true },
{ text: 'Item 4' },
{ text: 'Item 5', value: { foo: 'bar', baz: true } }
]
```

If `value` is missing, then `text` will be used as both the `value` and `text` fields. If you use
the `html` property, you **must** supply a `value` property.

Internally, BootstrapVue will convert the above array to the following array (the
[array of objects](#options-as-an-array-of-objects)) format:

<!-- eslint-disable no-unused-vars -->

```js
const options = [
{ text: 'Item 1', value: 'first', disabled: false },
{ text: 'Item 2', value: 'second', disabled: false },
{ html: '<b>Item</b> 3', value: 'third', disabled: true },
{ text: 'Item 4', value: 'Item 4', disabled: false },
{ text: 'Item 5', value: 'E', disabled: false }
]
```

### Changing the option field names

If you want to customize the field property names (for example using `name` field for display
`text`) you can easily change them by setting the `text-field`, `html-field`, `value-field`, and
`disabled-field` props to a string that contains the property name you would like to use:

```html
<template>
<div>
<b-form-radio-group
v-model="selected"
:options="options"
class="mb-3"
value-field="item"
text-field="name"
disabled-field="notEnabled"
></b-form-radio-group>
<div class="mt-3">Selected: <strong>{{ selected }}</strong></div>
</div>
</template>

<script>
export default {
data() {
return {
selected: 'A',
options: [
{ item: 'A', name: 'Option A' },
{ item: 'B', name: 'Option B' },
{ item: 'D', name: 'Option C', notEnabled: true },
{ item: { d: 1 }, name: 'Option D' }
]
}
}
}
</script>

<!-- b-form-radio-group-options-fields.vue -->
```

## Radio value and v-model

Expand Down
Loading

0 comments on commit f1ed017

Please sign in to comment.