Skip to content

[LiveComponent] Prevent uncollapse item on refresh #702

@bastien70

Description

@bastien70

Hello, I'm using LiveComponent to render an hardcore form with a lot of collections.

This form has collections inside collapsed div.
When clicking the button to "add" or "remove" a collection item, the item is added/removed but all is "uncollapsed".

Example :

demo_collapse.mp4

Unfortunately, I cannot add "data-live-ignore" in the div containing the collapsed content since otherwise the buttons allowing to add/remove an element from a collection will no longer refresh the fields.

I had another idea which was to set up a system that would save in the entities whether it's collapsed or not, and at refresh, would allow me to put everything back as it should be, but I find it restrictive, and I wonder if there isn't a better way?

This is how I render the form :

<ul class="list-group">
        <li class="list-group-item bg-danger text-white">
            <span class="badge bg-success rounded-pill"></span>
            <span class="ms-2 fs-5">Éléments de preuve et questionnaire</span>
        </li>
        {% for sous_dossier_index, sous_dossier_form in form.sousDossiers.children %}
            {% set sous_dossier = sous_dossier_form.vars.data %}
            <li class="list-group-item" style="background-color: #f8f9fa;" data-bs-toggle="collapse" data-bs-target="#sous_dossier_{{ sous_dossier_index }}" aria-expanded="false" aria-controls="sous_dossier_{{ sous_dossier_index }}">
                <div class="d-flex justify-content-between align-items-center" role="button">
                    <span class="fs-4">{{ sous_dossier.name }}</span>
                    <span class="badge bg-warning rounded-pill">&nbsp;</span>
                </div>
                <div id="sous_dossier_{{ sous_dossier_index }}" class="collapse">
                        <div class="row row-cols-1 row-cols-md-2 g-4">
                            {% for sous_dossier_item_index, sous_dossier_item_form in sous_dossier_form.items %}
                                {% set sous_dossier_item = sous_dossier_item_form.vars.data %}
                                <div class="col">
                                    <div class="card">
                                        <div class="card-header">{{ sous_dossier_item }}</div>
                                        <div class="card-body">
                                            {% set files_item = sous_dossier_item_form.files.children %}

                                            {% for file_index, file_item in files_item %}
                                                <button type="button"
                                                        class="btn btn-link text-danger"
                                                        data-action="live#action"
                                                        data-action-name="removeItem(sousDossierIndex={{ sous_dossier_index }}, sousDossierItemIndex={{ sous_dossier_item_index }}, fileIndex={{ file_index }})">
                                                    Retirer
                                                </button>
                                                {{ form_widget(file_item, {'attr': {'data-model': 'on(change)|norender|' ~ file_item.vars.full_name }}) }}
                                            {% endfor %}
                                        </div>
                                        <div class="card-footer">
                                            <button type="button"
                                                    class="btn btn-link float-start"
                                                    data-action="live#action"
                                                    data-action-name="addItem(sousDossierIndex={{ sous_dossier_index }}, sousDossierItemIndex={{ sous_dossier_item_index }})">
                                                Ajouter un élément
                                            </button>
                                            <button type="button" class="btn btn-sm btn-secondary float-end">
                                                <i class="fas fa-arrow-right"></i>
                                            </button>
                                        </div>
                                    </div>
                                </div>
                            {% endfor %}
                        </div>
                </div>
            </li>
        {% endfor %}
    </ul>

And in the component, my two liveAction to add or remove an item :

    #[LiveAction]
    public function removeItem(#[LiveArg] int $sousDossierIndex, #[LiveArg] int $sousDossierItemIndex, #[LiveArg] int $fileIndex): void
    {
        if (isset($this->formValues['sousDossiers'][$sousDossierIndex]['items'][$sousDossierItemIndex]['files'][$fileIndex])) {
            unset($this->formValues['sousDossiers'][$sousDossierIndex]['items'][$sousDossierItemIndex]['files'][$fileIndex]);
        }
    }

    #[LiveAction]
    public function addItem(#[LiveArg] int $sousDossierIndex, #[LiveArg] int $sousDossierItemIndex): void
    {
        $this->formValues['sousDossiers'][$sousDossierIndex]['items'][$sousDossierItemIndex]['files'][] = [];
    }

Thanks for your help!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions