# app/models/post.rb
class Post < ApplicationRecord
  def self.tags_suggestions
    # Example of an array of more advanced objects
    [
      {
        value: 1,
        label: 'one',
        avatar: 'https://images.unsplash.com/photo-1560363199-a1264d4ea5fc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&w=256&h=256&fit=crop',
      },
      {
        value: 2,
        label: 'two',
        avatar: 'https://images.unsplash.com/photo-1567254790685-6b6d6abe4689?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&w=256&h=256&fit=crop',
      },
      {
        value: 3,
        label: 'three',
        avatar: 'https://images.unsplash.com/photo-1560765447-da05a55e72f8?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&w=256&h=256&fit=crop',
      },
    ]
  end
end
```

</Option>

<Option name="`disallowed`">

The `disallowed` param works similarly to `suggestions`. Use it to prevent the user from adding specific values.

```ruby{3}
field :skills,
  as: :tags,
  disallowed: ["not", "that"]
```

<Image src="/assets/img/fields/tags-field/disallowed.gif" width="786" height="436" alt="Avo tags field" />

#### Default

`[]`

#### Possible values

An array of strings representing the value that can't be stored in the database.

</Option>

<Option name="`enforce_suggestions`">

Set whether the field should accept other values outside the suggested ones. If set to `true` the user won't be able to add anything else than what you posted in the `suggestions` option.

```ruby{4}
field :skills,
  as: :tags,
  suggestions: %w(one two three),
  enforce_suggestions: true
```

<Image src="/assets/img/fields/tags-field/enforce_suggestions.gif" width="786" height="436" alt="Avo tags field" />

#### Default

`false`

#### Possible values

`true`, `false`

</Option>

<Option name="`suggestions_max_items`">

Set of suggestions that can be displayed at once. The excessive items will be hidden and the user will have to narrow down the query to see them.

```ruby{4}
field :skills,
  as: :tags,
  suggestions: %w(one two three),
  suggestions_max_items: 2
```

<Image src="/assets/img/fields/tags-field/suggestions_max_items.gif" width="600" height="302" alt="Avo tags field - suggestions max items option" />

#### Default

`20`

#### Possible values

Integers
</Option>

<Option name="`close_on_select`">

Set whether the `suggestions` dropdown should close after the user makes a selection.

```ruby{4}
field :items,
  as: :tags,
  suggestions: -> { Post.tags_suggestions },
  close_on_select: true
```

<Image src="/assets/img/fields/tags-field/close_on_select.gif" width="786" height="436" alt="Avo tags field" />

#### Default

`false`

#### Possible values

`true`, `false`
</Option>

<Option name="`acts_as_taggable_on`">

Set the field the `acts_as_taggable_on` is set.

#### Default

`nil`

#### Possible values

Any string or symbol you have configured on your corresponding model.
</Option>

<Option name="`delimiters`">

Set the characters that will cut off the content into tags when the user inputs the tags.

```ruby{3}
field :skills,
  as: :tags,
  delimiters: [",", " "]
```

<Image src="/assets/img/fields/tags-field/delimiters.gif" width="786" height="436" alt="Avo tags field" />

#### Default

`[","]`

#### Possible values

`[",", " "]`

Valid values are comma `,` and space ` `.

</Option>

<Option name="`mode`">

By default, the tags field produces an array of items (ex: categories for posts), but in some scenarios you might want it to produce a single value (ex: dynamically search for users and select just one). Use `mode: :select` to make the field produce a single value as opposed to an array of values.

```ruby{3}
field :skills,
  as: :tags,
  mode: :select
```

#### Default

`nil`

#### Possible values

Valid values are `nil` for array values and `select` for a single value.

<Image src="/assets/img/fields/tags-field/mode-select.gif" width="800" height="666" alt="" />

</Option>

<Option name="`fetch_values_from`">

There might be cases where you want to dynamically fetch the values from an API. The `fetch_values_from` option enables you to pass a URL from where the field should suggest values.

This options works wonderful when used in Actions.

```ruby{3}
field :skills,
  as: :tags,
  fetch_values_from: "/avo/resources/skills/skills_for_user"
```

When the user searches for a record, the field will perform a request to the server to fetch the records that match that query.

<Image src="/assets/img/fields/tags-field/mode-select.gif" width="800" height="666" alt="" />

<br>

#### Default

`nil`

#### Possible values

Valid values are `nil`, a string, or a block that evaluates to a string. The string should resolve to an endpoint that returns an array of objects with the keys `value` and `label`.

The endpoint will receive the user input as `q` in the params. It is accessible by using `params["q"]`.
::: code-group

```ruby{2-10} [app/controllers/avo/skills_controller.rb]
class Avo::SkillsController < Avo::ResourcesController
  def skills_for_user
    # You can access the user input by using params["q"]
    skills = Skill.all.map do |skill|
      {
        value: skill.id,
        label: skill.name
      }
    end
    render json: skills
  end
end
```

```ruby{13} [config/routes.rb]
Rails.application.routes.draw do
  # your routes

  authenticate :user, ->(user) { user.is_admin? } do
    mount_avo
  end
end

if defined? ::Avo
  Avo::Engine.routes.draw do
    scope :resources do
      # Add route for the skills_for_user action
      get "skills/skills_for_user", to: "skills#skills_for_user"
    end
  end
end
```
:::

:::info
When using the `fetch_labels_from` pattern, on the <Show /> and <Index /> views you will see the `id` of those options instead of the label.
That is expected, because you are storing the `id`s in the database and the field can't know what labels those `id`s have.

To mitigate that use the `fetch_labels` option.
:::

</Option>

<Option name="`fetch_labels`">

:::warning
Deprecated since <Version version="3.10" /> in favor of `format_using`
:::

The `fetch_labels` option allows you to pass an array of custom strings to be displayed on the tags field. This option is useful when Avo is displaying a bunch of IDs and you want to show some custom label from that ID's record.

```ruby{4-6}
field :skills,
  as: :tags,
  fetch_values_from: "/avo/resources/skills/skills_for_user",
  fetch_labels: -> {
    Skill.where(id: record.skills).pluck(:name)
  }
```

In the above example, `fetch_labels` is a lambda that retrieves the names of the skills stored in the record's `skills` property.

When you use `fetch_labels`, Avo passes the current `resource` and `record` as arguments to the lambda function. This gives you access to the hydrated resource and the current record.

#### Default

Avo's default behavior on tags

#### Possible values

- Array of strings
</Option>

<Option name="`format_using`" since="3.10">

:::info
Since <Version version="3.10" />
:::

The `format_using` option allows you to pass an array of custom strings or hashes to be displayed on the tags field. This option is useful when Avo is displaying a bunch of IDs and you want to show some custom label from that ID's record.

```ruby{4-11}
field :skills,
  as: :tags,
  fetch_values_from: "/avo/resources/skills/skills_for_user",
  format_using: -> {
    Skill.find(value).map do |skill|
      {
        value: skill.id,
        label: skill.name
      }
    end
  }
```

In the above example, `format_using` is a lambda that retrieves the names and the ids of the skills stored in the record's `skills` property.

When you use `format_using`, Avo passes the `value`, current `resource` and `record` as arguments to the lambda function. This gives you access to the hydrated resource and the current record.

#### Default

Avo's default behavior on tags

#### Possible values

- Array of strings, notice that this will replace the DB values
- Array of hashes with `value` and `label` keys. WIll show the `label` and store the `value`
</Option>

## PostgreSQL array fields

You can use the tags field with the PostgreSQL array field.

```ruby{11}