# `WardrikWeb.Form`

Builds a form from a JSON Schema, and reads the submitted form back into a value.

| Schema | Form |
| --- | --- |
| string, number, boolean, enum | a field |
| object | a fieldset |
| array of objects | a group you can repeat |
| `oneOf` | a choice between the alternatives |
| string with `"writeOnly": true` | a password field |

    <WardrikWeb.Form.fields schema={schema} params={@params} />

    {:ok, input} = WardrikWeb.Form.read(schema, params["input"])

  * Fields are named `input[...]`. The submitted params hold them under `"input"`.
  * `params/2` fills the form with an existing value, for example a saved definition.
  * If the form has repeatable groups, handle the `"form-add"` and `"form-remove"` events with
    `handle/3`. Update `@params` on `phx-change`.
  * `read/2` leaves out empty fields.

# `kind`

```elixir
@type kind() ::
  :text
  | :long
  | :integer
  | :number
  | :switch
  | :choice
  | :const
  | :lines
  | :checks
  | :list
  | :object
  | :union
  | :json
  | :empty
```

The kind of form field a schema produces.

# `add`

```elixir
@spec add(map() | nil, [String.t()]) :: map()
```

Adds an empty group to the array of objects at `path` in `params`.

# `fields`

Renders the fields for an object `schema`, filled with `params`.

Use `:only` or `:except` to choose which top-level properties to show. Required fields come
first.

## Attributes

* `schema` (`:map`) (required)
* `params` (`:any`) - Defaults to `%{}`.
* `only` (`:list`) - Defaults to `nil`.
* `except` (`:list`) - Defaults to `[]`.
* `target` (`:any`) - The `phx-target` of the add and remove buttons. Defaults to `nil`.

# `handle`

```elixir
@spec handle(String.t(), map(), map() | nil) :: map() | nil
```

Handles the `"form-add"` and `"form-remove"` events. Returns the updated `params`.

Returns `nil` for any other event.

# `kind`

```elixir
@spec kind(map(), String.t() | nil) :: kind()
```

Returns the kind of field for `schema`. Long text fields, like `instructions`, get a text area.

# `params`

```elixir
@spec params(map(), term()) :: term()
```

Returns the params that fill a form for `schema` with `value`.

# `read`

```elixir
@spec read(map(), term()) :: {:ok, term()} | :none | {:error, String.t()}
```

Reads submitted `params` as a value of `schema`. Empty fields are left out. Returns `:none` if every field is empty.

# `remove`

```elixir
@spec remove(map() | nil, [String.t()]) :: map()
```

Removes the group at `path` in `params`.

---

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