# Cascader

> Pick a path through nested options shown in columns, and submit the whole path.

## Anatomy

A cascader picks a path through nested options shown in columns. Each choice opens the next column, and the form submits the whole path.

Write a [text field](/text-inputs.html.md) with the `cascader` class, holding a named `<input>`, its label and a `ul.cascader-options` of nested lists. Each `<li>` holds a `data-value`, and its label is its own text. `AutoInit()` starts every `.cascader`; the lists stay hidden, and the columns are built from them. Mark a leaf `data-selected` to start with its path.

 Place

-   United States
    -   California
        -   San Francisco
        -   Los Angeles
    -   New York
        -   New York City
        -   Buffalo
-   Mexico
    -   Jalisco
        -   Guadalajara
        -   Puerto Vallarta

```
<div class="field cascader">
  <input id="place" name="place" type="text" required>
  <label for="place">Place</label>
  <ul class="cascader-options">
    <li data-value="us">United States
      <ul>
        <li data-value="ca">California
          <ul>
            <li data-value="sf">San Francisco</li>
            <li data-value="la">Los Angeles</li>
          </ul>
        </li>
      </ul>
    </li>
    <li data-value="mx">Mexico</li>
  </ul>
</div>
```

## Keyboard

Enter, Space or ArrowDown opens the columns. ArrowDown and ArrowUp move within a column, and Home and End go to its ends. ArrowRight or Enter on a branch opens the next column, and ArrowLeft goes back to the option that opened it. Enter or Space on a leaf commits the path. Escape and Tab close without committing and return focus to the field. Under `dir="rtl"` the columns run right to left and the arrow keys swap.

## The submitted path

The field shows the path's labels, such as `United States / California / San Francisco`, and fires `input` and `change` when the path changes. The form gets one entry per level under the input's name, in order, so `new FormData(form).getAll('place')` returns `['us', 'ca', 'sf']`. A form reset brings back the starting path. With `required`, the form does not submit until a path is chosen. A disabled field submits nothing.

## Options and methods

`i18n.required` replaces the message a required field shows, from script or from `data-cascader-options` on the `.cascader`.

```
const place = Expressive.Cascader.getInstance(document.querySelector('.cascader'));
place.value;     // ['us', 'ca', 'sf'], or [] before a path is chosen
place.open();    // opens the columns at the chosen path
place.close();
place.destroy(); // removes the columns and gives the input back its name
```
