# `MishkaGervaz.Form.Entities.Field`
[🔗](https://github.com/mishka-group/mishka_gervaz/blob/v0.0.1-alpha.3/lib/mishka_gervaz/form/entities/field.ex#L1)

Form field — name, type, validation, access predicates, and an
optional `ui` sub-entity for label / placeholder / styling plus an
optional `preload` sub-entity for relation field eager-loading.

Field type is either a built-in token (`:text`, `:textarea`, `:select`,
`:relation`, `:nested`, etc.) or a module implementing
`MishkaGervaz.Form.Behaviours.FieldType`. When omitted, type is
inferred from the matching Ash attribute. Visibility (`visible` /
`restricted`) follows the standard predicate convention shared with
groups, headers, footers, and notices.

## Example

    fields do
      field :title, :text do
        required true
        position :first

        ui do
          label "Title"
          placeholder "Enter title..."
          span 2
        end
      end

      field :user_id, :relation do
        mode :search
        display_field :email
        search_field :email

        preload do
          always [:role]
        end
      end
    end

See `MishkaGervaz.Form.Dsl.Fields` for the surrounding section,
`MishkaGervaz.Form.Entities.Field.Ui` for the `ui` sub-entity,
`MishkaGervaz.Form.Entities.Field.Preload` for the `preload`
sub-entity, `MishkaGervaz.Form.Entities.NestedField` for sub-field
declarations inside a `:nested` field, and
`MishkaGervaz.Form.Behaviours.FieldType` for custom field types.

# `position`

```elixir
@type position() :: integer() | :first | :last | {:before, atom()} | {:after, atom()}
```

# `t`

```elixir
@type t() :: %MishkaGervaz.Form.Entities.Field{
  __identifier__: term(),
  __spark_metadata__: map() | nil,
  _nested_field_entities: term(),
  add_label: String.t() | nil,
  apply: (any(), any(), map() -&gt; any()) | nil,
  array_fields: list(),
  auto_fields: boolean(),
  default: any(),
  depends_on: atom() | nil,
  derive_value: (struct() -&gt; any()) | nil,
  display_field:
    atom() | (struct() -&gt; String.t()) | (struct(), map() -&gt; String.t()) | nil,
  format: (any() -&gt; any()) | (map(), map(), any() -&gt; any()) | nil,
  include_nil: boolean() | String.t() | (-&gt; String.t()),
  load: (any(), map() -&gt; any()) | nil,
  load_action: atom() | {atom(), atom()} | nil,
  max: integer() | nil,
  min: integer() | nil,
  min_chars: integer() | nil,
  mode: :static | :load_more | :search | :search_multi,
  name: atom(),
  nested_fields: list(),
  options: list() | (-&gt; list()) | nil,
  options_source: {module(), atom(), atom()} | nil,
  page_size: pos_integer(),
  position: position() | nil,
  preload: MishkaGervaz.Form.Entities.Field.Preload.t() | nil,
  readonly: boolean() | (map() -&gt; boolean()),
  remove_label: String.t() | nil,
  render:
    (struct() -&gt; Phoenix.LiveView.Rendered.t())
    | (struct(), map() -&gt; Phoenix.LiveView.Rendered.t())
    | nil,
  required: boolean(),
  resource: module() | nil,
  restricted: boolean() | (map() -&gt; boolean()),
  search_field: atom() | nil,
  show_on: :create | :update | nil,
  source: atom() | nil,
  type: atom() | module(),
  type_module: module() | nil,
  ui: MishkaGervaz.Form.Entities.Field.Ui.t() | nil,
  value_field: atom() | nil,
  virtual: boolean(),
  visible: boolean() | (map() -&gt; boolean())
}
```

# `transform`

Transform the field after DSL compilation.

Sets defaults, resolves the type_module, and extracts nested entities.

---

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