Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Commit

Permalink
Add label to OcSelect (#1570)
Browse files Browse the repository at this point in the history
* Add label to OcSelect

* OcSelect: Add optionLabel prop which is passed as label to vue-select

* Move input-id into additional attributes computed prop

Co-authored-by: Dominik Schmidt <dev@dominik-schmidt.de>
Co-authored-by: Benedikt Kulmann <benedikt@kulmann.biz>
  • Loading branch information
3 people authored Sep 6, 2021
1 parent ec7327e commit 088159b
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 10 deletions.
9 changes: 9 additions & 0 deletions changelog/unreleased/change-ocselect-label
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Change: Label for OcSelect

We've added a configurable `<label>` for OcSelect accessible via the `label` property.
This shadows the `label` property of `vue-select`. Hence we introduced the `optionLabel`
property on OcSelect which maps to the `label` property of `vue-select`.

https://github.com/owncloud/owncloud-design-system/pull/1633
https://github.com/owncloud/owncloud-design-system/pull/1570
https://github.com/owncloud/owncloud-design-system/issues/1503
120 changes: 110 additions & 10 deletions src/components/OcSelect.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
<template>
<vue-select ref="select" :value="model" class="oc-select" v-bind="$attrs" v-on="$listeners">
<template v-for="(index, name) in $scopedSlots" #[name]="data">
<slot :name="name" v-bind="data"></slot>
</template>
<div slot="no-options" v-translate>No options available.</div>
</vue-select>
<div>
<label :for="id" v-text="label" />
<vue-select
ref="select"
:value="model"
class="oc-select"
v-bind="additionalAttributes"
v-on="$listeners"
>
<template v-for="(index, name) in $scopedSlots" #[name]="data">
<slot :name="name" v-bind="data"></slot>
</template>
<div slot="no-options" v-translate>No options available.</div>
</vue-select>
</div>
</template>

<script>
import uniqueId from "../utils/uniqueId"
import VueSelect from "vue-select"
import "vue-select/dist/vue-select.css"
Expand All @@ -27,16 +37,55 @@ export default {
},
props: {
/**
* The ID of the element.
*/
id: {
type: String,
required: false,
default: () => uniqueId("oc-select-"),
},
/**
* The model of the select component. Provide it as value or bind it with v-model.
**/
model: {
type: [Array, String, Object],
required: false,
default: null,
},
/**
* Label of the select component
* ATTENTION: this shadows the vue-select prop `label`. If you need access to that use `optionLabel`.
*/
label: {
type: String,
default: null,
},
/**
* Key to use as label when option is an object
* NOTE: this maps to the vue-select prop `label`
*/
optionLabel: {
type: String,
default: null,
},
},
computed: {
additionalAttributes() {
const additionalAttrs = {}
additionalAttrs["input-id"] = this.id
if (this.optionLabel) {
additionalAttrs["label"] = this.optionLabel
}
return { ...this.$attrs, ...additionalAttrs }
},
},
mounted() {
this.setComboBoxAriaLabel()
},
methods: {
setComboBoxAriaLabel() {
const comboBoxElement = this.$refs.select.$el.querySelector("div:first-child")
Expand Down Expand Up @@ -98,7 +147,7 @@ For detailed documentation (props, slots, events, etc.), please visit https://vu
```js
<template>
<div class="oc-docs-width-medium">
<oc-select v-model="selected" :options="['Bannana', 'Orange', 'Pear']" />
<oc-select label="Custom label" v-model="selected" :options="['Bannana', 'Orange', 'Pear']" />
</div>
</template>
<script>
Expand Down Expand Up @@ -146,14 +195,65 @@ export default {
</script>
```

### Use objects as options
If we want to select from a list of option objects, we can use `option-label` to select the key of the object to use as label.

```js
<template>
<div class="oc-docs-width-medium">
<oc-select
label="Custom Label"
option-label="title"
:options="options"
v-model="selected"
class="oc-mb-m"
/>
</div>
</template>
<script>
const options = [
{
title: 'Apple',
desc: 'An apple is an edible fruit produced by an apple tree (Malus domestica)'
},
{
title: 'Bannana',
desc: 'Bannana is a genus of goblin spiders (family Oonopidae) native to Xishuangbanna prefecture, Yunnan Province, China, where it lives in the leaf-litter of tropical rainforest'
},
{
title: 'Orange',
desc: 'The orange is the fruit of various citrus species in the family Rutaceae'
},
]
export default {
data: () => ({
selected: options[1],
options
})
}
</script>
```




### Using slots to display complex options
Sometimes we need to display more complex options. This can include e.g. an option with a title and a description. To still display all those values exactly as we want to, we need to use scoped slot called `option`.
We can then retrieve all the values that we want to display from the slots parametres. It is important to specify the `label` prop on the `oc-select` component which will specify which key should be used as the option label.
Sometimes we need to display more complex options. This can include e.g. an option with a title and a description. To
still display all those values exactly as we want to, we need to use scoped slots called `option` and `selected-option`.
We can then retrieve all the values that we want to display from the slot parameters.
It is important to specify the `option-label` prop on the `oc-select` to make filtering work.

```js
<template>
<div class="oc-docs-width-medium">
<oc-select v-model="selected" :options="options" label="title" class="oc-mb-m">
<oc-select
label="Custom Label"
option-label="title"
:options="options"
v-model="selected"
class="oc-mb-m"
>
<template v-slot:option="{ title, desc }">
<span class="option">
<strong v-text="title" />
Expand Down

0 comments on commit 088159b

Please sign in to comment.