Howdy - I’m attempting to build a link aggregator app using Phoenix/Liveview. I have a form that when submit, creates a post that has an (optional) attached link. I want to create a button that fetches the title from the link and inserts it into the form. I’ve been having a hard time figuring that out!
The link and post entities are their own separate schemas.
Post schema:
schema "posts" do
field(:title, :string)
field(:text, :string)
belongs_to(:user, User)
belongs_to(:link, Link)
end
Link schema:
schema "links" do
field :url, :string
has_many(:posts, Post)
end
My form is populated with with the post using to_form(). Here’s what the form looks like right now:
I set up an <.inputs_for> so that I can create the button. How can I use that Fetch Title button to populate the Title section of the form? I don’t know what to put in my handle_event("fetch_title", ...). I’ve tried adding the a link section to the form, but that doesn’t seem to be helping.
Anyone have any ideas on how I should approach this? And also - please let me know if this is not the appropriate way to structure my form. I’m still a beginner to Phoenix/Liveview.
(PS. A nice to have would be if the URL isn’t valid - the validation would run through my Link.changeset and disable the Fetch Title button, but we’re not quite there yet.)
When you “retrieve on already in my DB” - will you be matching on the :url field?
If so, I do not think you should do it this way. 2 reasons.
If links can ever be changed then multiple posts sharing the same link would be bad, since the URL for 1 might have to change but not the others.
Matching the URL exactly will be annoying. You will have to account for different formats, e.g. “www.” or not, as well as for things like URL params that seem to be everywhere, e.g. https://example.com vs https://example.com?utm_campaign=email.
With both of these in mind, I would simply move the URL to the Post schema.
I do not know the full scope of what you are building so I might be completely wrong but that is my intuition.
I know you are asking for advice about using forms with changesets where there is associated data but I do not want to get into that when I think a simpler approach would be better.
That’s a really good point! I am matching on the :url field. I did think of the second scenario, but not the first. I’ll take your advice and change it to a field on the post. That is indeed much simpler. Thank you
Having said that - what would be the correct approach for building the form if I did need to do a get_or_insert on the associated data? I think there is a “hole” in my understanding on how the LiveView form propagates the data down, and similarly how the errors are bubbled back up on the correct input fields.
There are multiple ways to do it. In your case, it is a bit new for me. I have never done a form where the “parent” record was nested inside a “child” record.
That is, I am used to using inputs_for with has_one and has_many associations.
That said, when you use put_assoc or cast_assoc, the associated field will be a changeset or list of changesets. You can render the errors in the usual way. Look at phx-feedback-for usage in your autogenerated core_components.ex file. Ignore the red herring errors attribute, which lets you send custom errors. The trick is that phx-feedback-for will display errors for the form input with a certain name. If you want to get a good look at it for yourself, use put_assoc or cast_assoc and then build a form with to_form. Then IO.inspect(form) or IO.inspect(form.source) or IO.inspect(form.source.changes).