symfony / ux

Symfony UX initiative: a JavaScript ecosystem for Symfony
https://ux.symfony.com/
MIT License
836 stars 307 forks source link

[LiveComponent] "JS Error: Missing From Element originalData" with nested components #253

Closed glaubinix closed 2 years ago

glaubinix commented 2 years ago

I am using LiveComponent for a mix of filter/search and in place edit using one component for the searching and then a nested component to in place edit individual items, in twig my search component looks like:

<div
        {{ init_live_component(this) }}
        data-action="change->live#update"
>
     {{ form(this.form) }}

    {% for entry in this.entries %}
        {{ component('edit', {
            entry: entry
        }) }}
    {% endfor %}
</div>

The actual search component has a getEntries() method that returns entries based on the current form state

    public function getEntries(): array
    {
        $entries = [
            ['label' => 'Calzone', 'category' => 'pizza'],
            ['label' => 'Steak', 'category' => 'not-pizza'],
            ['label' => 'Flatbread', 'category' => 'pizza'],
            ['label' => 'Pasta', 'category' => 'not-pizza'],
        ];
        if ($this->request->category !== null) {
            $entries = array_filter($entries, fn (array $entry) => $entry['category'] === $this->request->category);
        }

        return $entries;
    }

My edit component in twig then looks like and has live actions to toggle the edit mode

<div
        {{ init_live_component(this) }}
>
    <p>
        {% if this.isEdit %}
            <input type="text" value="{{ this.label }}">
            <a href="#" data-action="live#action" data-action-name="prevent|cancelEdit">Cancel</a>
        {% else %}
            {{ this.label }}
            <a href="#" data-action="live#action" data-action-name="prevent|showEdit">Edit</a>
        {% endif %}
    </p>
</div>

This all works as expected. However, triggering more than one form update will trigger the JS error below. The reason for this seems to be that data-original-data is removed from the edit components.

live_controller.js:1471 Uncaught (in promise) Error: Missing From Element originalData
    at extended._shouldChildLiveElementUpdate (live_controller.js:1471:1)
    at onBeforeElUpdated (live_controller.js:1366:1)
    at morphEl (live_controller.js:492:1)
    at morphChildren (live_controller.js:605:1)
    at morphEl (live_controller.js:507:1)
    at morphdom (live_controller.js:722:1)
    at extended._executeMorphdom (live_controller.js:1357:1)
    at extended._processRerender (live_controller.js:1224:1)
    at live_controller.js:1199:1

I can work around this by adding data-original-data="{}" to the edit component to avoid the JS error. However, the component then still loses their state, in this case whether it should be rendered as input or text.

I have a fully working example https://github.com/glaubinix/ux-live-component-nested

benr77 commented 2 years ago

I have a very similar issue with nested components triggering this same JS error.

weaverryan commented 2 years ago

Apologies for the delay - THANK YOU for the reproducer. Fixed over at #293