Alter a "DeadView" Phoenix.HTML.Form based on the value of one of its fields?

(I am not seeing a straightforward way to do this – not without Javascript anyway – but I figured I’d ask, just in case.)

I want to alter my Phoenix HTML form, depending on the value of one of its fields, whenever that value changes.

In the silly non-working example below, the form’s text changes whenever the :answer field selection changes. This pseudocode “accomplishes” this with the help of the magical function evaluate_on_every_form_data_change(current_field_values), which “computes” the appropriate text every time a field on the form changes:

app.html.heex:

<main class="container">
...
   <%= form_for @conn, Routes.api_controller_item_path(@conn, :new_item), fn f -> %>
      <%= select f, :answer, ["Yes!!": "yes", "Nope": "no"], selected: "yes" %> 
      <%= evaluate_on_every_form_data_change(f, fn current_field_values -> %>
          <%= if current_field_values.answer == "yes" do %>
              <%= "OMG YAY" %>
          <% else %>
              <%= "SAD" %>
          <% end %>
      <% end ) %>
   
     <%= submit "Submit" %>
   <% end %>
...

Obviously, evaluate_on_every_form_data_change(form_data) is not a thing, but if anyone has any suggestions / pointers (or can confirm the futility of this endeavor;), I’m super-interested.

Thank you!
Mark.

EDIT: to clarify, this is NOT a LiveView form.

The short answer is that there is no way to do this without javascript.

After the backend ships a page out to the client, the HTTP request is done and the server and client no longer have any relationship. If the browser is going to take any further action, then there needs to be JS shipped alongside the HTML that the browser can run. That JS could either handle this sort of thing on its own, or it could boot a websocket connection and establish a LiveView connection so that the client and server again have a relationship.

To make the client’s page change, the client’s browser has to run code. The only code that client’s browser is going to run is JS(1).

(1) There’s some shenanigans you can pull with CSS and checkboxes but it’s pretty hacky.

3 Likes

This makes perfect sense, thank you!