Tags field
Adding a list of things to a record is something we need to do pretty frequently; that's why having the tags
field is helpful.
field :skills, as: :tags
Options
-> suggestions
WARNING
This warning no longer applies Since v3.11.8
If you're using this field as filterable
, dynamic filters are not yet picking these suggestions.
Please use the custom dynamic filters suggestions option to specify filter suggestions.
You can give suggestions to your users to pick from which will be displayed to the user as a dropdown under the field.
# app/avo/resources/course.rb
class Avo::Resources::Course < Avo::BaseResource
def fields
field :skills, as: :tags, suggestions: -> { record.skill_suggestions }
end
end
# app/models/course.rb
class Course < ApplicationRecord
def skill_suggestions
['example suggestion', 'example tag', self.name]
end
end
Default
[]
Possible values
The suggestions
option can be an array of strings, an object with the keys value
, label
, and (optionally) avatar
, or a lambda that returns an array of that type of object.
The lambda is run inside a ExecutionContext
, so it has access to the record
, resource
, request
, params
, view
, and view_context
along with other things.
# 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
-> disallowed
The disallowed
param works similarly to suggestions
. Use it to prevent the user from adding specific values.
field :skills,
as: :tags,
disallowed: ["not", "that"]
Default
[]
Possible values
An array of strings representing the value that can't be stored in the database.
-> 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.
field :skills,
as: :tags,
suggestions: %w(one two three),
enforce_suggestions: true
Default
false
Possible values
true
, false
-> suggestions_max_items
field :skills,
as: :tags,
suggestions: %w(one two three),
suggestions_max_items: 2
Default
20
Possible values
Integers
-> close_on_select
field :items,
as: :tags,
suggestions: -> { Post.tags_suggestions },
close_on_select: true
Default
false
Possible values
true
, false
-> acts_as_taggable_on
Default
nil
Possible values
Any string or symbol you have configured on your corresponding model.
-> delimiters
Set the characters that will cut off the content into tags when the user inputs the tags.
field :skills,
as: :tags,
delimiters: [",", " "]
Default
[","]
Possible values
[",", " "]
Valid values are comma ,
and space .
-> 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.
field :skills,
as: :tags,
mode: :select
Default
nil
Possible values
Valid values are nil
for array values and select
for a single value.
-> 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.
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.
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
.
class Avo::SkillsController < Avo::ResourcesController
def skills_for_user
skills = Skill.all.map do |skill|
{
value: skill.id,
label: skill.name
}
end
render json: skills
end
end
Rails.application.routes.draw do
# your routes
authenticate :user, ->(user) { user.is_admin? } do
mount Avo::Engine, at: Avo.configuration.root_path
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
-> fetch_labels
WARNING
Deprecated since 3.10.0 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.
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
-> format_using
INFO
Since 3.10.0
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.
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
andlabel
keys. WIll show thelabel
and store thevalue
PostgreSQL array fields
You can use the tags field with the PostgreSQL array field.
# app/avo/resources/course.rb
class Avo::Resources::Course < Avo::BaseResource
def fields
field :skills, as: :tags
end
end
# db/migrate/add_skills_to_courses.rb
class AddSkillsToCourses < ActiveRecord::Migration[6.0]
def change
add_column :courses, :skills, :text, array: true, default: []
end
end
Acts as taggable on
One popular gem used for tagging is acts-as-taggable-on
. The tags field integrates very well with it.
You need to add gem 'acts-as-taggable-on', '~> 9.0'
in your Gemfile
, add it to your model acts_as_taggable_on :tags
, and use acts_as_taggable_on
on the field.
# app/avo/resources/post.rb
class Avo::Resources::Post < Avo::BaseResource
def fields
field :tags,
as: :tags,
acts_as_taggable_on: :tags,
close_on_select: false,
placeholder: 'add some tags',
suggestions: -> { Post.tags_suggestions },
enforce_suggestions: true,
help: 'The only allowed values here are `one`, `two`, and `three`'
end
end
# app/models/post.rb
class Post < ApplicationRecord
acts_as_taggable_on :tags
end
That will let Avo know which attribute should be used to fill with the user's tags.
Related
You can set up the tags as a resource using this guide.
Array fields
We haven't tested all the scenarios, but the tags field should play nicely with any array fields provided by Rails.
# app/avo/resources/post.rb
class Avo::Resources::Post < Avo::BaseResource
def fields
field :items, as: :tags
end
end
# app/models/post.rb
class Post < ApplicationRecord
def items=(items)
puts ["items->", items].inspect
end
def items
%w(1 2 3 4)
end
end