Is it possible to control LiveView from load state?

Hi,

I have a LiveView where form submission triggers a long-running process, and I prefer to do it in the background and then update the page via PubSub when it’s done.

Of course, form input and submit buttons should be blocked during that time, which I have out of the box with a synchronous process (i.e. if handle_event doesn’t return).

Is it possible to reuse that functionality in the async flow, that is - return from handle_event but keep the form in loading and turn it off later on?

You can use a boolean @loading assign to DIY.

4 Likes

Since LiveView has a hardcoded PUSH_TIMEOUT and async processing is a suggested pattern it would nice if complementing UI functionality would be provided by a framework :slight_smile:

This functionality does exist in the framework/language. There are tasks, GenServers and various PubSub options and the template language is extremely flexible. What do you imagine the framework could provide for this use case that would be easier than setting a boolean or checking for the presence of a task ref?

Also, if you think blocking the UI for 30s is ok then you might want to read some UX books :wink:

Just extending what is already there - making phx-disable-with="..." and topbar working with async updates and keeping it declarative.

Also, if you think blocking the UI for 30s is ok then you might want to read some UX books :wink:

Or get a common sense :smiley: That’s for the prototype.

I prefer

        <.button type="submit" class="x__button x__button--primary" phx-disable-with="Loading...">
          Show transactions
        </.button>

to

 <.button type="submit" class="x__button x__button--primary" disabled={@importing}>
          <%= if @importing do %>
            Loading...
          <% else %>
            Show transactions
          <% end %>
        </.button>

and boolean flag manipulation

You’d need extra options though, and you’re probably veering into the oncoming traffic of implicit behaviour and magic. Talk us through the lifecycle of how you imagine this could work.

From the top of my head phx-in-progress attribute on the form can do the trick.

A relatively new option here that may end up a bit cleaner in some scenarios:

<.button :if={!@disabled} class=“…”>Submit</.button>

<.button :if={@disabled} disabled class=“…”><.my_spinner />Loading</.button>

This causes some things to be duplicated of course, but I’m finding that it’s much more readable in many scenarios, especially for tags that have 2-3+ attrs/content that depend on a shared condition. (Of course this isn’t fundamentally different to a top-level if, but I find reduction in nesting improves html readability.)

1 Like

Thanks for the highlight! This is definitely a step in right direction IMO.
Now imagine how cool it would be to have groups/variations of controls managed by a single property.

Let’s say

<form>
<.button variations=[{:loading, @loading}] variation-disabled=[:loading] variation-text=[{:loading, "Loading"}]> Submit</button>
</form> 

Something of this sorts.

I wonder how that would map on the Phx Live Storybook @cblavier :thinking:

1 Like

I have no clue :person_shrugging: :sweat_smile:

1 Like

You could make a component that does this.

1 Like