Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Updates correct scope when x-for looping over element with x-data #3504

Merged
merged 4 commits into from May 11, 2023

Conversation

ekwoka
Copy link
Contributor

@ekwoka ekwoka commented Apr 1, 2023

solves #3447 (demos and discussion exist there)

<template x-for="item in my_array" :key="item.k">
        <div x-data="{ foo: 'bar' }" >
            <div x-text="item.x"></div>
        </div>
    </template>

When looping over an iterable with x-for, and the first child has an x-data scope, if the array changed, now containing new objects but which had the same key value, the scope would improperly update.

This fixes that.

The cause

The x-for does update the scope of the child, but it naively would update only the newest scope on the element. The problem is that this would be, during the update, the scope created by the x-data and not the x-for. The effects registered to the looped over object/values would be within the context of the x-for provided synthetic scope. This scope would continue to have the initial value.

The fix

Store reference to the scope provided by x-for and use that to directly update the synthetic scope, instead of naively updating the latest scope.

@calebporzio
Copy link
Collaborator

Good catch, thanks for this. Because refreshScope was only used inside x-for, I decided to pull it into x-for.js and refactor it a bit to avoid that conditional "fromXFor" flag.

Thanks again!

@calebporzio calebporzio merged commit 117668f into alpinejs:main May 11, 2023
1 check passed
addScopeToNode(clone, reactiveScope, templateEl)

clone._x_refreshXForScope = (newScope) => {
Object.entries(newScope).forEach(([key, value]) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can actually be optimized to just

Object.assign(reactiveScope[key], newScope)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants