# `Drafter.WidgetValue`
[🔗](https://github.com/jaman/drafter/blob/main/lib/drafter/widget_runtime/widget_value.ex#L1)

Reads and writes a widget's primary value by the shape of its state.

There is no per-widget-type table: `extract/1` tries the shapes below in order and
takes the first one the state satisfies, and `update_props/2` maps a new value back
onto the props that set it. `Drafter.get_widget_value/1`,
`Drafter.set_widget_value/2` and the app loop's own value lookup all come through
here, so every path answers alike.

Recognised shapes, in order:

  * `:text` — that string. `text_input`, `text_area`, `label`, `button`, `link`,
    `loading_indicator`, `digits`, `placeholder`.
  * `:checked` — a boolean. `checkbox`.
  * `:state` holding `:on` or `:off` — `true` for `:on`. `switch`.
  * `:selected_index` with `:options` — the id of the option at that index.
    `radio_set`, `option_list`.
  * `:selected_indices` with `:options` — the ids of those options. `selection_list`.
  * `:expanded` — a boolean. `collapsible`.
  * `:active_tab` — the active tab index. `tabbed_content`.
  * `:selected_rows` — that `MapSet` as a list. `data_table`.
  * `:selected_nodes` — that `MapSet` as a list. `tree`.
  * `:value` with `:min`, `:max` and `:step` — that number. `slider`.

Anything else reads as `nil`.

# `extract`

```elixir
@spec extract(map() | struct() | nil) :: term() | nil
```

The primary value held in `state`, or `nil` when no shape matches and for `nil`.

    iex> Drafter.WidgetValue.extract(%{text: "hello"})
    "hello"

    iex> Drafter.WidgetValue.extract(%{state: :on})
    true

    iex> Drafter.WidgetValue.extract(%{value: 0.5, min: 0.0, max: 1.0, step: nil})
    0.5

    iex> Drafter.WidgetValue.extract(%{selected_index: 1, options: [%{id: :a}, %{id: :b}]})
    :b

    iex> Drafter.WidgetValue.extract(nil)
    nil

# `update_props`

```elixir
@spec update_props(map() | struct() | nil, term()) :: map() | nil
```

The props that write `value` into `state`, or `nil` when it cannot be written.

Only three of the shapes `extract/1` reads are writable, and the value must match
the field's type.

    iex> Drafter.WidgetValue.update_props(%{text: "old"}, "new")
    %{text: "new"}

    iex> Drafter.WidgetValue.update_props(%{value: 0.5, min: 0.0, max: 1.0, step: nil}, 0.9)
    %{value: 0.9}

    iex> Drafter.WidgetValue.update_props(%{checked: false}, "yes")
    nil

---

*Consult [api-reference.md](api-reference.md) for complete listing*
