LiveView propagate phx-change on hidden_input

Hello! I have a LiveView generated on “scheduler” model with --live, where the model has (among others) a “date_range_start” field that is a Date type. The form_component generated with date_select inputs, and I have been working on changing those into a calendar-picker LiveComponent. It’s been going great, except I’m having trouble getting the phx-change event (“validate”) to propagate when the hidden_inputs that I’ve slotted into the Calendar component change, and I’m trying to figure out why since those hidden_inputs are clearly tied to the form etc.

Some code:


  <.form
    let={f}
    for={@changeset}
    id="scheduler-form"
    phx-target={@myself}
    phx-change="validate"
    phx-submit="save">
  
    <%= label f, :title %>
    <%= text_input f, :title %>
    <%= error_tag f, :title %>
  
    <%= label f, :date_range_start %>
    <.live_component
      module={MyApp.SchedulerLive.CalendarComponent}
      id="scheduler-calendar-date_range_start"
      form={f}
      let={current_date}
    >
      <%= hidden_input f, :date_range_start, name: "#{f.name}[date_range_start][year]", value: Timex.format!(current_date, "%Y", :strftime) %>
      <%= hidden_input f, :date_range_start, name: "#{f.name}[date_range_start][month]", value: Timex.format!(current_date, "%-m", :strftime) %>
      <%= hidden_input f, :date_range_start, name: "#{f.name}[date_range_start][day]", value: Timex.format!(current_date, "%-d", :strftime) %>
    </.live_component>
    <%= error_tag f, :date_range_start %>
  
    <%= label f, :date_range_end %>

    <%= date_select f, :date_range_end %>
    <%= error_tag f, :date_range_end %>
  
    <div>
      <%= submit "Save", phx_disable_with: "Saving..." %>
    </div>
  </.form>

The CalendarComponent has no trouble choosing a current_date, and I can see the generated input type="hidden" tags changing when it does, but no "validate" event is getting handled by the LiveComponent when it does so (it is handled for all the other inputs, including that second date_select that I haven’t replaced yet). I turn to the broader community, humbly, for help with this.

Setting form values from JS by default doesn‘t trigger change events (for legitimate reasons/usecases), so you need to manually trigger them for phoenix to pick up: JavaScript interoperability — Phoenix LiveView v0.17.9

1 Like

Ah, that was the page that explains this, thanks for the pointer, I was searching all over for the page that would explain this behavior.

The documentation pointed to above gives the building blocks but doesn’t put them together, so for posterity, I added a Hook with this:

Hooks.PublishInput = {
  updated() {
    this.el.dispatchEvent(
      new Event("input", {bubbles: true})
    )
  }
}

then my hidden_input tags within the slot for the calendar component got this:

      <%= hidden_input f,
        :date_range_start,
        id: "scheduler-date-range-start-year",
        'phx-hook': "PublishInput",
        name: "#{f.name}[date_range_start][year]",
        value: Timex.format!(current_date, "%Y", :strftime)
      %>

From here it can be abstracted into a helper to tidy it up, but this got me to functional. Thanks again, LostKobrakai!