# Inputs >> Select Rich >> Features ||20 ```js script import { LitElement, html } from '@lion/core'; import '@lion/listbox/define'; import '@lion/listbox/define'; import '@lion/select-rich/define'; ``` ## 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. ```js preview-story export const optionsWithHTML = () => html`

I am red

and multi Line

I am hotpink

and multi Line

I am teal

and multi Line

`; ``` ## Many Options with Scrolling ```js preview-story export const manyOptionsWithScrolling = () => 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. ```js preview-story export const readOnlyPrefilled = () => html` Red Hotpink Teal `; ``` ## Disabled Select 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. ```js preview-story export const disabledSelect = () => html` Red Hotpink Teal `; ``` ```js preview-story export const disabledOption = () => html` Red Blue Hotpink Green 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. ```js preview-story export const renderOptions = ({ shadowRoot }) => { const objs = [ { type: 'mastercard', label: 'Master Card', amount: 12000, active: true }, { type: 'visacard', label: 'Visa Card', amount: 0, active: false }, ]; function showOutput(ev) { shadowRoot.getElementById('demoRenderOutput').innerHTML = JSON.stringify( ev.target.modelValue, null, 2, ); } return html` ${objs.map( obj => html` ${obj.label} `, )}

Full value:


  `;
};
```

## 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.

```js preview-story
export const interactionMode = () => html`
  
    Red
    Hotpink
    Teal
  
  
    Red
    Hotpink
    Teal
  
`;
```

## Checked index & value

You can get/set the checkedIndex and checkedValue.

```js preview-story
export const checkedIndexAndValue = ({ shadowRoot }) => html`
  
  
{ const selectEl = shadowRoot.getElementById('checkedRichSelect'); selectEl.checkedIndex = e.target.value; }} />
Red Hotpink Teal `; ``` ## No default selection If you want to set a placeholder option with something like 'Please select', you can of course do this, the same way you would do it in a native select. Simply put an option with a modelValue that is `null`. ```html select a color ``` However, this allows the user to explicitly select this option. Often, you may want a placeholder that appears initially, but cannot be selected explicitly by the user. For this you can use `has-no-default-selected` attribute. ```js preview-story export const noDefaultSelection = () => html` Red Hotpink Teal `; ``` > By default, the placeholder is completely empty in the `LionSelectInvoker`, > but subclassers can easily override this in their extension, by the overriding `_noSelectionTemplate()` method. ## Single Option If there is a single option rendered, then `singleOption` property is set to `true` on `lion-select-rich` and invoker as well. Invoker also gets `single-option` which can be used to having desired templating and styling. As in here the arrow is not displayed for single option ```js preview-story export const singleOption = () => html` Red `; ``` When adding/removing options the `singleOption` will only be `true` when there is exactly one option. ```js preview-story class SingleOptionRemoveAdd extends LitElement { static get properties() { return { options: { type: Array }, }; } constructor() { super(); this.options = ['Option 1', 'Option 2']; } render() { return html` ${this.options.map( option => html` ${option} `, )} `; } addOption() { this.options.push(`Option ${this.options.length + 1} with a long title`); this.options = [...this.options]; this.requestUpdate(); } removeOption() { if (this.options.length >= 2) { this.options.pop(); this.options = [...this.options]; this.requestUpdate(); } } } customElements.define('single-option-remove-add', SingleOptionRemoveAdd); export const singleOptionRemoveAdd = () => { return html``; }; ``` ## 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.childNodes); // 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.