Skip to content

Commit

Permalink
feat(form-select): Add multiple select support (issue #619) (#731)
Browse files Browse the repository at this point in the history
* feat(form-options): Add multiple select support to mixin

* [form-select] Support multiple select

Adds multiple elect support to form-select.

new props:
- `multiple` enabled multiple select support
- `multiple-size` set the number of rows displayed in multiple select. Defaults to browser default size

* docs(form-select): Document multiple select option
  • Loading branch information
tmorehouse committed Jul 28, 2017
1 parent c8ad5a3 commit 19bf2f5
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 58 deletions.
138 changes: 88 additions & 50 deletions docs/components/form-select/README.md
@@ -1,46 +1,7 @@
# Form Select

> Bootstrap custom `<select>` using custom styles. Provide options based on an array, array of objects. or an object.
```html
<template>
<div>
<b-form-select v-model="selected" :options="options" class="mb-3">
</b-form-select>

<div>Selected: <strong>{{ selected }}</strong></div>
</div>
</template>

<script>
export default {
data: {
selected: null,
options: [
{
text: 'Please select some item',
value: null
},
{
text: 'This is First option',
value: 'a'
}, {
text: 'Default Selected Option',
value: 'b'
}, {
text: 'This is another option',
value: 'c'
}, {
text: 'This one is disabled',
value: 'd',
disabled: true
}]
}
}
</script>

<!-- form-select.vue -->
```
> Bootstrap custom `<select>` using custom styles. Provide options based on an
array, array of objects. or an object.

### Options
`options` can be an array or a key-value object. Available fields:
Expand All @@ -49,7 +10,8 @@ export default {
- **`value`** The selected text which will be set on `v-model`
- **`disabled`** Disables item for selection

If you want to customize fields (for example using `name` field for display text) you can easily change them using `text-field` and `value-field` props.
If you want to customize fields (for example using `name` field for display text)
you can easily change them using `text-field` and `value-field` props.

#### Array:

Expand All @@ -76,17 +38,92 @@ Keys are mapped to value and values are mapped to option object.
a: 'Item A',
b: 'Item B',
c: 'Item C',
d: {text: 'D', disabled: true},
e: {text: 'D', value:'overridden_value'}
d: {text: 'Item D', disabled: true},
e: {text: 'Item E', value:'overridden_value'}
}
```

### Value
By Default `b-form-select` returns the value of the currently selected option. By
setting the `return-object` prop to `true`, you can return the entire option object.
### Standard (single) select
By default, Bootstrap V4's custom select styling is applied.

#### Value:
In non `multiple` mode, `<b-form-select>` returns the `value` of the currently
selected option as a string.

**Example 1: Custom Select (default)**
```html
<template>
<div>
<b-form-select v-model="selected" :options="options" class="mb-3">
</b-form-select>
<div>Selected: <strong>{{ selected }}</strong></div>
</div>
</template>

<script>
export default {
data: {
selected: null,
options: [
{ value: null, text: 'Please select some item' },
{ value: 'a', text: 'This is First option' },
{ value: 'b', text: 'Default Selected Option' },
{ value: 'c', text: 'This is another option' },
{ value: 'd', text: 'This one is disabled', disabled: true }
]
}
}
</script>

<!-- form-select-1.vue -->
```

### Multiple select support
Enable multiple select mode by setting the prop `multiple`, and control how many
rows are displayed in the multiple select list-box by setting `multiple-size` to
the number of rows to display. The default is to let the browser use it's default
(typically 4).

Multiple select does not support Bootstrap's custom select styling, so it will
be rendered using a native browser multi-select, but with the `.form-control`
class applied.

#### Value:
In `multiple` mode, `<b-form-select>` always returns an array of option values.
You should always provide an array reference as your `v-model` when in `multiple` mode.

**Example 2: Multiple Select**
```html
<template>
<div>
<b-form-select multiple :multiple-size="4" v-model="selected" :options="options" class="mb-3">
</b-form-select>
<div>Selected: <strong>{{ selected }}</strong></div>
</div>
</template>

<script>
export default {
data: {
selected: ['b'],
options: [
{ value: 'a', text: 'This is First option' },
{ value: 'b', text: 'Default Selected Option' },
{ value: 'c', text: 'This is another option' },
{ value: 'd', text: 'This one is disabled', disabled: true },
{ value: 'e', text: 'This is option e' },
{ value: 'f', text: 'This is option f' },
{ value: 'g', text: 'This is option g' }
]
}
}
</script>

<!-- form-select-2.vue -->
```

### Control sizing
Set heights using thw `size` prop to `sm` or `lg` for small or large respectively.
Set heights using the `size` prop to `sm` or `lg` for small or large respectively.

To control width, place the input inside standard Bootstrap grid column.

Expand All @@ -102,7 +139,7 @@ soft validation before a user attempts to submit a form.
- `success` is ideal for situations when you have per-field validation throughout a form
and want to encourage a user through the rest of the fields.

To apply one of the contextual steates on `<b-form-select>`, set the `state` prop
To apply one of the contextual states on `<b-form-select>`, set the `state` prop
to `danger`, `warning`, or `success` on the `<b-form-fieldset>` that wraps
the `<b-form-select>`.

Expand All @@ -117,7 +154,7 @@ providing an additional help text block (via `<b-form-fieldet>`). Specifically f
assistive technologies, invalid form controls can also be assigned
an `aria-invalid="true"` attribute (see below).

### ARIA `aria-invalid` attribute
#### ARIA `aria-invalid` attribute
When `<b-form-select>` has an invalid contextual state (i.e. `danger`) you may also
want to set the `<b-form-select>` prop `invalid` to `true`.

Expand All @@ -127,3 +164,4 @@ Supported `invaid` values are:

### Non custom select
Set the prop `plain` to have a native browser `<select>` rendered.
Multiple select will always render as a `plain` select.
22 changes: 20 additions & 2 deletions lib/components/form-select.vue
Expand Up @@ -3,6 +3,8 @@
:name="name"
:id="id || null"
v-model="localValue"
:multiple="multiple || null"
:size="multiple && multipleSize > 1 ? multipleSize : null"
:disabled="disabled"
:required="required"
:aria-required="required ? 'true' : null"
Expand All @@ -19,20 +21,21 @@

<script>
import { formMixin, formOptionsMixin, formCustomMixin } from '../mixins';
import { warn } from '../utils';
export default {
mixins: [formMixin, formCustomMixin, formOptionsMixin],
data() {
return {
localValue: this.value
localValue: this.multiple ? (this.value || []) : this.value
};
},
computed: {
inputClass() {
return [
'form-control',
this.size ? `form-control-${this.size}` : null,
this.custom ? 'custom-select' : null
(this.custom && !this.multiple) ? 'custom-select' : null
];
},
ariaInvalid() {
Expand All @@ -56,10 +59,25 @@
type: [Array, Object],
required: true
},
multiple: {
type: Boolean,
default: false
},
multipleSize: {
// Browsers default size to 0, which typically shows 4 rows in most browsers
// Size of 1 can bork out firefox
type: Number,
default: 0
},
returnObject: {
type: Boolean,
default: false
}
},
created() {
if (this.returnObject) {
warn('form-select: return-object has been deprecated and will be removed in future releases');
}
}
};
Expand Down
14 changes: 8 additions & 6 deletions lib/mixins/form-options.js
Expand Up @@ -43,23 +43,25 @@ export default {
},
selectedValue() {
const formOptions = this.formOptions;
for (let i = 0; i < formOptions.length; i++) {
if (formOptions[i].value === this.localValue) {
if (this.returnObject) {
if (this.returnObject && !this.multiple) {
for (let i = 0; i < formOptions.length; i++) {
if (formOptions[i].value === this.localValue) {
return formOptions[i];
}
return formOptions[i].value;
}
return null;
} else {
return this.localValue;
}
}
},
props: {
valueField: {
type: [String],
type: String,
default: 'value'
},
textField: {
type: [String],
type: String,
default: 'text'
}
},
Expand Down

0 comments on commit 19bf2f5

Please sign in to comment.