calebgasser
How would i go about creating an input field for tags?
I may be going about this the wrong way but I can’t seem to figure out a good way to handle input for “tags” in a blog post. I’ve looked at using .inputs_for but I don’t want to create an input field for every tag. Ideally, it would just be a single text input that spits the value on spaces and transforms those into “tag” structs. Maybe this would be better to do outside a form?
I’ve been messing with it for hours and this doesn’t seem like it should be that difficult. Hopefully someone can point out an easier way I’m missing. Here is what I have right now (back to square one because the handful of things I tried hadn’t worked).
form_component.ex
#...
@impl true
def render(assigns) do
~H"""
<div>
<.header>
<%= @title %>
<:subtitle>by <%= @post.author %></:subtitle>
</.header>
<.simple_form
:let={form}
for={@form}
id="post-form"
as={"post_form"}
phx-target={@myself}
phx-change="validate"
phx-submit="save"
>
<.input field={@form[:title]} type="text" label="Title" />
<.input field={@form[:tags]} type="text" label="Tags"/> # <<<< This doesn't work, of course.
<.input field={@form[:author]} type="hidden" />
<.input field={@form[:body]} type="textarea" label="Body" />
<:actions>
<.button phx-disable-with="Saving...">Save Post</.button>
</:actions>
</.simple_form>
</div>
"""
end
# ...
post.ex
defmodule Personal.Blog.Post do
use Ecto.Schema
import Ecto.Changeset
schema "posts" do
field :author, :string
field :body, :string
field :title, :string
field :views, :integer, default: 0
many_to_many(:tags, Personal.Blog.Tag, join_through: "post_tags", on_replace: :delete)
timestamps(type: :utc_datetime)
end
@doc false
def changeset(post, attrs) do
post
|> cast(attrs, [:title, :author, :body, :views])
|> validate_required([:title, :author, :body, :views])
end
end
tag.ex
defmodule Personal.Blog.Tag do
use Ecto.Schema
import Ecto.Changeset
schema "tags" do
field :name, :string, default: ""
many_to_many(:posts, Personal.Blog.Post, join_through: "post_tags", on_replace: :delete)
timestamps(type: :utc_datetime)
end
@doc false
def changeset(tag, attrs) do
tag
|> cast(attrs, [:name])
|> validate_required([:name])
end
end
post_tag.ex
defmodule Personal.Blog.PostTag do
use Ecto.Schema
import Ecto.Changeset
schema "post_tags" do
belongs_to(:posts, Personal.Blog.Post)
belongs_to(:tags, Personal.Blog.Tag)
timestamps(type: :utc_datetime)
end
@doc false
def changeset(post_tag, attrs) do
post_tag
|> cast(attrs, [:post_id, :tag_id])
|> validate_required([:post_id, :tag_id])
end
end
Marked As Solved
codeanpeace
There’s a bit to unpack here as tagging implementations often vary to support different use cases. For example, do you want that text input to also act like a typeahead with suggestions/autocomplete for existing tags? Do you allow creations of new tags on the fly? Do you want to support removing added tags?
Here’s a relevant article on Buy paugramming.com – Premium Expired .com Domain on GoDaddy | ExpiredDomains.com that demonstrates how to create a client side hook which watches for comma seperated tags. And here’s previous discussion on Building a dynamic select component (in Phoenix LiveView?) - #4 by kartheek and filtering/narrowing down options based on a typeahead input.
Also Liked
trisolaran
You can also give LiveSelect a try. It doesn’t split values on spaces though.
calebgasser
This looks promising, I don’t want to have to reinvent the wheel if there is a good solution out there for it. Although, if it’s a simple thing to impliement it might be better to avoid the dependency. I’ll give it another shot after going through the resources people have provided me here and if it turns out to be too much work I’ll turn to this. Thanks a ton, I appreciate the resource!
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









