subsaharancoder
I have a phoenix app consisting of Posts & comments. A post can have many comments. I’m trying to put together a nested input form but failing with one of the handle events. Here is my code:
defmodule LiveBlogWeb.BlogLive.New do
alias LiveBlog.Blog.Comment
use LiveBlogWeb, :live_view
alias LiveBlog.Blog
alias LiveBlog.Blog.Post
alias LiveBlog.Blog.Comment
@impl true
def mount(_params, _session, socket) do
changeset = Blog.change_post(%Post{comments: [%Comment{}]})
# changeset = Blog.change_post(%Post{comments: [%Comment{}]})
form =
%Post{}
|> Post.changeset(%{})
|> to_form(as: "post")
{:ok, socket |> assign(form: form, changeset: changeset)}
end
@impl true
def handle_event("validate", %{"post" => post_params}, socket) do
post = Ecto.Changeset.apply_changes(socket.assigns.changeset)
changeset =
Blog.change_post(post, post_params)
|> Map.put(:action, :validate)
{:noreply, assign(socket, changeset: changeset)}
end
def handle_event("save", %{"post" => post_params}, socket) do
case Blog.create_post(post_params) do
{:ok, _post} ->
{:noreply,
socket
|> put_flash(:info, "Post created successfully.")
|> push_navigate(to: "/blog")}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, changeset: changeset)}
end
end
def handle_event("remove-comment", %{"index" => index}, socket) do
index = String.to_integer(index)
params = socket.assigns.changeset.params || %{}
post = Ecto.Changeset.apply_changes(socket.assigns.changeset)
# data = socket.assigns.changeset.data
changeset =
post
|> Blog.change_post(params)
# comments = get_comments_from_changeset(changeset)
comments = Ecto.Changeset.get_field(changeset, :comments, [])
updated_comments = List.delete_at(comments, index)
updated_changeset =
post
|> Blog.change_post(params)
|> Ecto.Changeset.put_assoc(:comments, updated_comments)
|> Map.put(:action, :validate)
{:noreply, assign(socket, changeset: updated_changeset)}
end
def handle_event("add-comment", _params, socket) do
# Handle adding a comment if needed
params = socket.assigns.changeset.params || %{}
# data = socket.assigns.changeset.data
post = Ecto.Changeset.apply_changes(socket.assigns.changeset)
changeset = Blog.change_post(post, params)
# changeset =
# socket.assigns.changeset.data
# |> Blog.change_post(params)
current_comments = Ecto.Changeset.get_assoc(changeset, :comments)
updated_comments = current_comments ++ [%Comment{}]
IO.inspect(updated_comments)
updated_changeset =
post
|> Blog.change_post(params)
|> Ecto.Changeset.put_assoc(:comments, updated_comments)
|> Map.put(:action, :validate)
# changeset =
# %Post{}
# |> Post.changeset(%{})
# |> Ecto.Changeset.put_assoc(:comments, updated)
{:noreply, assign(socket, changeset: updated_changeset)}
end
defp get_comments_from_changeset(changeset) do
case Ecto.Changeset.get_field(changeset, :comments, []) do
nil -> [%Comment{}]
comments -> comments
end
end
@impl true
def render(assigns) do
~H"""
<div class="max-w-4xl mx-auto py-8 px-4">
<h1>New Post</h1>
<.form :let={f} for={@changeset} id="post-form" phx-submit="save">
<.input field={f[:title]} type="text" label="Title" required />
<.input field={f[:summary]} type="text" label="Summary" required />
<.input field={f[:body]} type="textarea" label="Body" required />
<div id="comments">
<.inputs_for :let={comment} field={f[:comments]}>
<.input
field={comment[:body]}
type="textarea"
label="Comment"
placeholder="Start a comment"
/>
<.button type="button" phx-click="remove-comment" phx-value-index={comment.index}>
Remove
</.button>
</.inputs_for>
</div>
<.button phx-click="add-comment" type="button">
Add Comment
</.button>
<div class="flex justify-end">
<.button phx-disable-with="Saving...">Save</.button>
</div>
</.form>
</div>
"""
end
end
add-comment event adds a new comment input form, but when I try and delete I get the following error:
warning] found duplicate primary keys for association/embed `:comments` in `LiveBlog.Blog.Post`. In case of duplicate IDs, only the last entry with the same ID will be kept. Make sure that all entries in `:comments` have an ID and the IDs are unique between them
Also filling in the post form resets the comments section. Any idea what i’m doing wrong?
Trending in Questions
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
apply_graft/2 doesn’t rewrite an add_many sub-workflow’s deps on an add step. Grafted jobs cancel with “upstream job was deleted”
Version...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #blog-post
- #ai
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
Hermanverschooten
Check out Phoenix.Component — Phoenix LiveView v1.2.5, it was created especially for thes3ckind of situations.
subsaharancoder
thanks! I’ll check it out, I was already using the
inputs_forcomponent, I’ve now modified by Post Ecto Schema to match the docs but I’m using ahas_manyassociation notembeds_many. My final Post Schema looks like this:I’ll go through the live view
handle_eventcalls and work it slowly. I’ll update once I make some progress…Hermanverschooten
It doesn’t matter if it’s a
has_manyor embedded, it works the same.I implemented it a couple of days ago, works great.
subsaharancoder
Updated my live view code and that seems to have solved the duplicate primary keys error by adding a UUID for each new nested entry:
But now there’s a weird bug where when I click on save it adds a new nested input instead of persisting the data. I’ve looked at my save
handle_eventand nothing seems out of place. The save event works fine if I’m not appending new comments, just adding one comment. Any idea what is going on?Hermanverschooten
I think you are missing or misinterpreted some of the information in the link I gave you.
You don’t need handlers for adding/removing comments, by using the combination of
sort_paramanddrop_paramEctodoes this for you.Let me show you how I used it just a couple of days ago.
I have a
Companythat has 1 or moreIdentifiersand I needed to be able to manage them.This is the company schema:
and
These are the relevant functions in the
Companiesmodule;And this is the whole live view page:
I hope this helps.
kokolegorille
Can You show the Comment schema? I guess You are not using autogenerated id, of type binary_id
subsaharancoder
Thanks for this, started everything from scratch with a new app and schema, Department ->[has_many] Employees. The nested inputs work in terms of adding and removing employees, but weirdly clicking on the save does nothing, I can see the params in the terminal but nothing is being persisted. Here is my live view code:
Hermanverschooten
What comes back from your Catalog.create_company function?
subsaharancoder
I don’t have a Catalog.create_company function, I do have a Catalog.create_department function and the params look like this if I add a Department and one employee.
Hermanverschooten
Sorry, my bad, department it was. Still I would like to see the result of that function with your input, add a |> dbg() to it and post the result.