{html`
Red
Hotpink
Teal
`}
```html
Red
Hotpink
Teal
```
## Features
- Fully accessible
- Flexible api
- Fully customizable option elements
- Fully customizable invoker element
- Mimics native select interaction mode (windows/linux and mac)
## How to use
### Installation
```sh
npm i --save @lion/select-rich
```
```js
import '@lion/select-rich/lion-select-rich.js';
import '@lion/select-rich/lion-options.js';
import '@lion/select-rich/lion-option.js';
```
> No need to npm install `@lion/option` separately, it comes with the rich select as a dependency
## Examples
### Model value
You can set the full `modelValue` for each option, which includes the checked property for whether it is checked or not.
```html
Red
```
### Options with HTML
The main feature of this rich select that makes it rich, is that your options can contain HTML.
{html`
I am red
and multi Line
I am hotpink
and multi Line
I am teal
and multi Line
`}
```html
I am red
and multi Line
I am hotpink
and multi Line
I am teal
and multi Line
```
### Many Options with Scrolling
{html`
I am red
I am hotpink
I am teal
I am green
I am blue
`}
```html
I am red
I am hotpink
I am teal
I am green
I am blue
```
### Read only prefilled
You can set the rich select as read only.
This will block the user from opening the select.
The readonly attribute is delegated to the invoker for disabling opening the overlay, and for styling purposes.
{html`
Red
Hotpink
Teal
`}
### Disabled
You can set the `disabled` attribute to disable either specific options or the entire select.
If you disable the entire select, the disabled attribute is also delegated to the invoker, similar to readonly.
{html`
Red
Hotpink
Teal
Red
Blue
Hotpink
Green
Teal
`}
```html
Red
Hotpink
Teal
```
```html
Red
Blue
Hotpink
Green
Teal
```
### Validation
Validation can be used on this field as well, same as with other fields. Below is an example with required.
It can be triggered by opening the select and selecting a valid option, then selecting the first option again, of which the `modelValue` is `null`.
{() => {
loadDefaultFeedbackMessages();
return html`
select a color
Red
Hotpink
Teal
`;
}}
```js
import { loadDefaultFeedbackMessages, Required } from '@lion/validate';
```
```html
select a color
Red
Hotpink
Teal
```
### Render options
The choiceValue can also be a complex value like an Object.
It is up to you how to render this Object in the DOM.
{() => {
const objs = [
{ type: 'mastercard', label: 'Master Card', amount: 12000, active: true },
{ type: 'visacard', label: 'Visa Card', amount: 0, active: false },
];
function showOutput() {
document.getElementById('demoRenderOutput').innerHTML = JSON.stringify(
this.checkedValue,
null,
2,
);
}
return html`
${objs.map(
obj => html`
${obj.label}
`,
)}
Full value:
`;
}}
```js
const objs = [
{ type: 'mastercard', label: 'Master Card', amount: 12000, active: true },
{ type: 'visacard', label: 'Visa Card', amount: 0, active: false },
];
```
```html
${objs.map(
obj => html`
${obj.label}
`,
)}
```
### Interaction Mode
You can set the interaction mode to either `mac` or `windows/linux`.
By default, it will choose based on the user Operating System, but it can be forced.
This changes the keyboard interaction.
{html`
Red
Hotpink
Teal
Red
Hotpink
Teal
`}
```html
Red
Hotpink
Teal
```
```html
Red
Hotpink
Teal
```
### Checked index & value
You can get/set the checkedIndex and checkedValue.
{html`
Set the checkedIndex
{
const selectEl = document.getElementById('checkedRichSelect');
selectEl.checkedIndex = e.target.value;
}}
>
{
const selectEl = document.getElementById('checkedRichSelect');
console.log(`checkedIndex: ${selectEl.checkedIndex}`);
console.log(`checkedValue: ${selectEl.checkedValue}`);
}}>Console log checked index and value
Red
Hotpink
Teal
`}
```html
Red
Hotpink
Teal
```
```js
console.log(`checkedIndex: ${selectEl.checkedIndex}`); // 1
console.log(`checkedValue: ${selectEl.checkedValue}`); // 'hotpink'
selectEl.checkedIndex = 0;
console.log(`checkedIndex: ${selectEl.checkedIndex}`); // 0
console.log(`checkedValue: ${selectEl.checkedValue}`); // 'red'
```
### Custom Invoker
You can provide a custom invoker using the invoker slot.
This means it will get the selected value(s) as an input property `.selectedElement`.
You can use this `selectedElement` to then render the content to your own invoker.
```html
...
```
An example of how such a custom invoker class could look like:
```js
class MyInvokerButton extends LitElement() {
static get properties() {
return {
selectedElement: {
type: Object,
};
}
}
_contentTemplate() {
if (this.selectedElement) {
const labelNodes = Array.from(this.selectedElement.querySelectorAll('*'));
// Nested html in the selected option
if (labelNodes.length > 0) {
// Cloning is important if you plan on passing nodes straight to a lit template
return labelNodes.map(node => node.cloneNode(true));
}
// Or if it is just text inside the selected option, no html
return this.selectedElement.textContent;
}
return ``;
}
render() {
return html`
${this._contentTemplate()}
`;
}
}
```
> This example only works if your option elements don't have ShadowDOM boundaries themselves.
> Cloning deeply only works up until the first shadow boundary.