Second attempt at setting up my first LiveView

I posted this question before, but I am feeling like that approach was a little bulky.

To recap, I am trying to set up behavior like the following diagram:

I have a LiveView set up that renders the form for a car (it’s not really a car. something much less interesting) but the form works correctly on the initial render. If I click the edit car link, the from pops up in the modal correctly.

I am trying to pass the current car_id to the LiveView, but I think I am misunderstanding how this works.

The liveview is rendered in the page using:

<%= live_render @conn, UrmedWebappWeb.FormModalComponent, conn: @conn %>

I initially tried to start the chain of events by using Hooks, and doing something like:

<a id="ds-<%= ds.id %>" ref="#" data-bs-toggle="modal" data-bs-target="#exampleModal"
    phx-click="update_diagnosis_symptom_form"
    phx-value-ds-id="<%= ds.id %>"
    phx-hook="UpdateDiagnosisSymptomForm">
    Edit
</a>

But I am now wondering if this approach will work at all, as I have something totally simple in my hook, like:

let Hooks ={}

Hooks.UpdateDiagnosisSymptomForm = {
    mounted() {
        console.log("mounted");
    }
}

let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken, hooks: Hooks}})

when I click the link, nothing happens. the modal displays, but I get nothing in my console log. I am wondering if these bindings work only if I use them from inside a LiveView.

It seems like my problem is that I need to send a message from some random place on the dom (outside the LiveView) to the LiveView.

Am I completely off track here?

1 Like

It looks like you’re mixing two technologies : standard MVC templating for the list & LiveView for the modal ?(
It is feasible but not the easiest way to learn a new technology.

What is preventing you from coding both list & modal in liveview?

2 Likes

Also You use bootstrap 5 modal, liveview and hooks (hooks with phx-click, without phx-update), that is a huge mix :slight_smile:

A simple way is to see how it is done with generators.

mix phx.new koko --live
cd koko
mix phx.gen.live MyContext Todo todos title:string

It will generate a modal component.

yes, I am using the LiveView to render the the bootstrap modal, and standard MVC to the list. the list is also spread across 4 bootstrap tabs.

I think i could put it all in one LiveView, but that seems like it could get messy. The illustration I included has all of the complexity stripped from it.

My line of thinking was this. If I set up a LiveView that rendered the form inside the modal, I could just pass the ID of the car that i wanted to render the form for, and display the modal. I was thinking that it’s really just a LiveView that needs to get an input from somewhere in the dom.

Everything works correctly: the LiveView renders, the form is set up correctly, the modal displays, etc. I just can’t figure out how to send the ID to the LiveView.

Thanks!

Thanks! i will build that, and take a look.

I guess you can:

  • post a custom event to window from your javascript, catch it from within the liveView javascript hook, then push_event back to the server, on the server side update the liveView assigns in handle_event.
  • or, do a AJAX request back to the server, in the controller post a message to Phoenix.pubsub, catch it in the liveview’s handle_info, then update the liveview assigns

Quite a mouthful, but doable.

Normally, in Rails (which I used for a bazillion years before) I would just send an ajax call, and have it send the fully formed HTML back.

Do Hooks and phx-click only work inside a live view?

Of cause you can do that, but it is not liveview, but “deadview” then.
You send the ajax call, and get back a HTML fragment that you can inject into a modal as an innerHTML of a element. Problem is the fragment is dead now and has no live server-side part to do the live form validation for you.

Right. I was just illustrating how i was doing it before. I really want to make this work in LiveView… but I am just missing the part on sending some data to the LiveView from some random place in the dom… some place that is not being rendered by the LiveView.

I’ve come to realize that although live view is built on phoenix, it is a entirely a different kind of beast. Live view and “dead view” each have their own frontend and backend. To cross talk, you can either throw the message over the fence in the frontend or in the backend, but either way it is not going to be as smooth as working within their respective domains.

The way to do it with liveview is to build components.

Modal is just a special component, that take another component as part of state.

Everything should react when the state change. It would be as if You have @is_modal boolean, and when true, the modal is shown.

It is inspired by js framework, except the state is on the server :slight_smile:

1 Like

okay, this is starting to get clearer. i think i am going to try to put the entire thing in one LiveView. If that doesn’t work, i’ll do it in components. Thanks for your help!

1 Like

You can get an idea of how we’re using our own modal here: Phenix Storybook (it’s our private project storybook)

You won’t have the code of the Modal component by itself but you can see how modal state is managed by the liveview

2 Likes