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
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_resource.rb
class CourseResource < Avo::BaseResource
field :skills, as: :tags, suggestions: -> { record.skill_suggestions }
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 RecordHost
, so it has access to the record
along with other things (check the link).
# 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
-> dissallowed
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
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.
-> disallowed
-> 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 enddpoint 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
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
PostgreSQL array fields
You can use the tags field with the PostgreSQL array field.
# app/avo/resources/course_resource.rb
class CourseResource < Avo::BaseResource
field :skills, as: :tags
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_resource.rb
class PostResource < Avo::BaseResource
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
# 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_resource.rb
class PostResource < Avo::BaseResource
field :items, as: :tags
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