Skip to content

Commit a3de399

Browse files
committed
bug #1326 [LiveComponent] Fix - data-loading expressions not working on root node (WebMamba)
This PR was merged into the 2.x branch. Discussion ---------- [LiveComponent] Fix - data-loading expressions not working on root node | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | Issues | Fix #1325 | License | MIT Commits ------- 346dae7 [LiveComponent] Fix - data-loading expressions not working on root node
2 parents bb32456 + 346dae7 commit a3de399

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

src/LiveComponent/assets/dist/live_controller.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2392,7 +2392,11 @@ class LoadingPlugin {
23922392
}
23932393
getLoadingDirectives(element) {
23942394
const loadingDirectives = [];
2395-
element.querySelectorAll('[data-loading]').forEach((element => {
2395+
let matchingElements = element.querySelectorAll('[data-loading]');
2396+
if (element.hasAttribute('data-loading')) {
2397+
matchingElements = [element, ...matchingElements];
2398+
}
2399+
matchingElements.forEach((element => {
23962400
if (!(element instanceof HTMLElement) && !(element instanceof SVGElement)) {
23972401
throw new Error('Invalid Element Type');
23982402
}

src/LiveComponent/assets/src/Component/plugins/LoadingPlugin.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,15 @@ export default class implements PluginInterface {
155155
getLoadingDirectives(element: HTMLElement|SVGElement) {
156156
const loadingDirectives: ElementLoadingDirectives[] = [];
157157

158-
element.querySelectorAll('[data-loading]').forEach((element => {
158+
let matchingElements = element.querySelectorAll('[data-loading]');
159+
160+
// querySelectorAll doesn't include the element itself
161+
if (element.hasAttribute('data-loading')) {
162+
// add element at the beginning of matchingElements
163+
matchingElements = [element, ...matchingElements];
164+
}
165+
166+
matchingElements.forEach((element => {
159167
if (!(element instanceof HTMLElement) && !(element instanceof SVGElement)) {
160168
throw new Error('Invalid Element Type');
161169
}

src/LiveComponent/assets/test/controller/loading.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,35 @@ describe('LiveController data-loading Tests', () => {
4848
expect(getByTestId(test.element, 'loading-element')).not.toBeVisible();
4949
});
5050

51+
it('executes basic loading functionality on root element', async () => {
52+
const test = await createTest({food: 'pizza'}, (data: any) => `
53+
<div ${initComponent(data)} data-loading="addClass(opacity-20)">
54+
<span>I like: ${data.food}</span>
55+
<button data-action="live#$render">Re-Render</button>
56+
</div>
57+
`);
58+
59+
test.expectsAjaxCall()
60+
.serverWillChangeProps((data: any) => {
61+
// to help detect when rendering is done
62+
data.food = 'popcorn';
63+
})
64+
// delay so we can check loading
65+
.delayResponse(50);
66+
67+
// wait for element to hide itself on start up
68+
await waitFor(() => expect(test.element).not.toHaveClass('opacity-20'));
69+
70+
getByText(test.element, 'Re-Render').click();
71+
// element should instantly be visible
72+
expect(test.element).toHaveClass('opacity-20');
73+
74+
// wait for loading to finish
75+
await waitFor(() => expect(test.element).toHaveTextContent('I like: popcorn'));
76+
// loading element should now be hidden
77+
expect(test.element).not.toHaveClass('opacity-20');
78+
});
79+
5180
it('takes into account the "action" modifier', async () => {
5281
const test = await createTest({}, (data: any) => `
5382
<div ${initComponent(data)}>

0 commit comments

Comments
 (0)