err0r500

err0r500

Hi,
I recently hit a performance issue with a liveview form.

The structure the form edits has lots of association handled dynamically using cast_assoc.
Everything works fine for ~70% of the cases (with just a few assocs), but the 30 remaining percents can have more 100, 200 assocs and the users struggle a lot. In this kind of cases, websocket frames can be 30, 40 KB on each validation.

Just to give a feel of what the form does (and simplify things), let’s imagine it allows to edit staff in a movie :

movie (with a few specific fields, like title, length...)
  -> has many professions (10+, must validate uniqueness in movie and not empty, with a few specific fields) 
       -> has many people (100+, must validate uniqueness in profression and not empty, with a few specific fields)

people are managed somewhere else, i just create a drop down so they can pick a person and add a few metadata for this peculiar profession 

To stay in the example, most of my users manage indie movies with less than 40 people and everything works well, the issue are the blockbusters (and the UI should be able to handle both, so keep everything in a single page without modals or tabs or navigation because for most of my users the form is not that big. )

Do you have any advices about how to handle this ?
Best,
Matthieu

Showing Posts 1 to 7

LostKobrakai

LostKobrakai

I’d start by evaluating if all that data needs to be handled through one huge form. I’d argue nobody wants to scrolls through a list of 200 entries editing all of them at once. They rather scroll hrough a list of 200 entries, and on some click an edit button to make some targeted small edits.

If you still want to stick to that large a form check out the RC for LV 1.1, which has optimizations for for comprehentions as used by inputs_for.

err0r500

err0r500 OP

Thanks a lot for your response,

I agree about the UX of editing a big list. Actually, such big forms weren’t expected at first (I’d like to qualify them as “edge cases” if they weren’t happening ~15% of the time).

In fact, the users don’t edit much in these lists, they just add/remove references and i currently use cast_assoc sort_param & drop_param to achieve this. This works fine with small-sized forms but not for big ones.

90% of the websocket frame is just _unused_<field> i’m not sure what they’re used for and if it might be a solution to just not send them.

upgrading to LV1.1 seem not to improve much in my case (I guess it would if i were managing the list specifically)

LostKobrakai

LostKobrakai

That’s to me further insight to make this a static list with means of adding, sorting removing individual items with individual forms and actions handling instead of craming it all into a shared parent form.

Those are used to determine which inputs have been “touched” by a user to hide errors for not yet touched inputs.

err0r500

err0r500 OP

I agree, I already made an attempt to split the form and gave up after a few hours : i just have to figure out how not to nest them and keep the complexity not to high (because the movie example is a simplification : in my app, i have ~20 schemas involved with up to 4 levels of nesting) :smiley:

alright, I’ll leave them !

PJUllrich

PJUllrich

Author of Building Table Views with Phoenix LiveView

Without knowing your form structure, it’s difficult to give advice, but in my experience, it’s sometimes easier to not wrap every table entry in one huge form, but to make each e.g. a LiveComponent with one form per row.

This way, you only need to handle a form for one record at a time. If you only have a Delete action per row, you don’t even need the form, just delete the record from the database and remove the LiveComponent from the template (e.g. with stream_delete/3)

For editing, you can either have the row become a form or you could show a modal to edit the record.

To add new records, you can have a single form at the end of the table which would create a single new record.

garrison

garrison

See used_input?/1 in the docs for more about the _unused_* keys.

err0r500

err0r500 OP

I got some good results by splitting the form into several smaller ones with a dedicated changeset for each one. this led to a notable improvement about what the client sends to the server.
I then realized that on the server response there was a big select that was sent back each time (and for each element of the form) so I encapsulated it in a livecomponent that gets its options once then renders them only for edition.
for saving I merge all forms .params (it seems to work fine) and apply that to the global changeset.
the result is much more efficient (but I had to change a bit the layout and the UX to achieve that)

Thanks for your help !

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
ryanwinchester
apply_graft/2 doesn’t rewrite an add_many sub-workflow’s deps on an add step. Grafted jobs cancel with “upstream job was deleted” Version...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews