Skip to content

[LiveComponent] Fix loadingDirectives match elements from nested components #1392

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

Conversation

smnandre
Copy link
Member

Q A
Bug fix? yes
New feature? no
Issues Fix #1382
License MIT

The elements with loading directives were used in all LiveController they were in.

This PR fixes that and restrict loadingDirective to the scope of the LiveContoller (and filter those belonging to nested / child components)

Copy link
Member

@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

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

Thanks for getting on this. Possible to add a test too - should be able to combine something from child.test.js into loading.test.js.

let matchingElements = [...element.querySelectorAll('[data-loading]')];

// ignore elements which are inside a nested "live" component
matchingElements = matchingElements.filter((elt) => elt.closest('[data-controller~="live"]') === element);
Copy link
Member

Choose a reason for hiding this comment

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

We have a built-in mechanism for this we should use - it's elementBelongsToThisComponent from dom_utils.ts. We can pass the component instance from LoadingPlugin.attachToComponent into the callbacks, then into here so we can call that.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think using the DOM will be better in term of performance, as we just manipulate Node element.. but that could be challenged. Do you want to use it for now ?

We could probably use only a CSS selector but i think we need to define this browser compatibility list before :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Test added @weaverryan

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for adding the test! I still think we should use elementBelongsToThisComponent(). By not using it, we're adding "dangling code": we have just one part of the code that works differently than everywhere else. We would need a real, verified performance reason to do such a thing. And, except for cases where there actually are children (which is not most live components), the elementBelongsToThisComponent() is basically just a call to element.contains() - https://github.com/symfony/ux/blob/2.x/src/LiveComponent/assets/src/dom_utils.ts#L204

Copy link
Member Author

Choose a reason for hiding this comment

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

Made changes, i cannot test locally for now, is this how you imagined it ?

@@ -2393,7 +2393,8 @@ class LoadingPlugin {
}
getLoadingDirectives(element) {
const loadingDirectives = [];
let matchingElements = element.querySelectorAll('[data-loading]');
let matchingElements = [...element.querySelectorAll('[data-loading]')];
matchingElements = matchingElements.filter((elt) => elt.closest('[data-controller~="live"]') === element);
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not sure about the use of the closest function. closest finds only one element, but in a live component you can have multiple elements with a loading attribute in nested element

Copy link
Member Author

Choose a reason for hiding this comment

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

closest is an ascending selector, it look the first parent "live controller"

let matchingElements = [...element.querySelectorAll('[data-loading]')];

// ignore elements which are inside a nested "live" component
matchingElements = matchingElements.filter((elt) => elt.closest('[data-controller~="live"]') === element);
Copy link
Member

Choose a reason for hiding this comment

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

Thanks for adding the test! I still think we should use elementBelongsToThisComponent(). By not using it, we're adding "dangling code": we have just one part of the code that works differently than everywhere else. We would need a real, verified performance reason to do such a thing. And, except for cases where there actually are children (which is not most live components), the elementBelongsToThisComponent() is basically just a call to element.contains() - https://github.com/symfony/ux/blob/2.x/src/LiveComponent/assets/src/dom_utils.ts#L204

@weaverryan weaverryan added Bug Bug Fix Status: Needs Work Additional work is needed labels Jan 29, 2024
@smnandre smnandre force-pushed the fix/loading-directives-parent-child-components branch 2 times, most recently from cbf694f to c769ac4 Compare January 29, 2024 20:43
@smnandre smnandre requested a review from weaverryan January 29, 2024 21:22
Copy link
Member

@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

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

One minor tweak needed - thanks!

component.on('loading.state:started', (element: HTMLElement, request: BackendRequest) => {
this.startLoading(element, request);
component.on('loading.state:started', (element: HTMLElement, request: BackendRequest, component: Component) => {
this.startLoading(component, element, request);
Copy link
Member

Choose a reason for hiding this comment

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

We already have the component as the argument to attachToComponent and we're attaching the loading.state.started to that specific component. So o need for the new argument to the callback: we can use the component variable already

Copy link
Member Author

Choose a reason for hiding this comment

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

As i could not test, i did it in a defensive way :)

I'll remove it

Copy link
Member Author

Choose a reason for hiding this comment

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

Fix / rebased / rebuilded (style cannot test locally -- will fix this next week)

Copy link
Member Author

Choose a reason for hiding this comment

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

Think i did what you meant but not sure

@carsonbot carsonbot added Status: Needs Review Needs to be reviewed and removed Status: Needs Work Additional work is needed labels Jan 30, 2024
@smnandre smnandre force-pushed the fix/loading-directives-parent-child-components branch 2 times, most recently from 1da752b to af3882c Compare January 30, 2024 15:02
@smnandre smnandre requested a review from weaverryan January 30, 2024 15:04
@weaverryan weaverryan force-pushed the fix/loading-directives-parent-child-components branch from af3882c to 7867e44 Compare January 30, 2024 15:36
@weaverryan
Copy link
Member

Thanks Simon!

@weaverryan weaverryan merged commit ed57804 into symfony:2.x Jan 30, 2024
@smnandre
Copy link
Member Author

Oh damn... i was pushing to rebase .... hope i did not mess on the go with things

@weaverryan
Copy link
Member

All good, I merged before you rebased. I did the rebasing ;)

weaverryan added a commit that referenced this pull request Feb 29, 2024
…ase 🚀 (weaverryan)

This PR was squashed before being merged into the 2.x branch.

Discussion
----------

[Live][Stimulus] Prepping the LiveComponent Stable Release 🚀

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| Issues        | None
| License       | MIT

Hi!

LiveComponents has, really, been quite stable for a long time, but it's kept its experimental status. Removing that is really about deciding that we'll protect backwards-compatibility. It's time to do that :).

This is planned as the 2.15.0 release near the end of Feb (assuming we get the items below done before then).

TODOs:

* #1418
* Possibly remove Twig 2.x compat
* #1428
* #1392
* Moving `Idiomorph` to a peer dependency would be great, but blocked by bigskysoftware/idiomorph#35 - **still need a tag** for the PR merge
* #1426 as it may include some edge-case BC breaks.

If there's anything else on your mind before stable, now is the time to mention it :).

Cheers!

Commits
-------

7932a9d [Live][Stimulus] Prepping the LiveComponent Stable Release 🚀
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Bug Fix Status: Needs Review Needs to be reviewed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[LiveComponent] data-loading behaviour not working correctly in child components
5 participants