Skip to content

Commit 3e2a7db

Browse files
committed
Make getLoadingDirectives "component-aware"
Add 'component' to loading events in a BC compatible way
1 parent 6463ffb commit 3e2a7db

File tree

5 files changed

+38
-37
lines changed

5 files changed

+38
-37
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ interface ElementLoadingDirectives {
88
}
99
export default class implements PluginInterface {
1010
attachToComponent(component: Component): void;
11-
startLoading(targetElement: HTMLElement | SVGElement, backendRequest: BackendRequest): void;
12-
finishLoading(targetElement: HTMLElement | SVGElement): void;
11+
startLoading(component: Component, targetElement: HTMLElement | SVGElement, backendRequest: BackendRequest): void;
12+
finishLoading(component: Component, targetElement: HTMLElement | SVGElement): void;
1313
private handleLoadingToggle;
1414
private handleLoadingDirective;
15-
getLoadingDirectives(element: HTMLElement | SVGElement): ElementLoadingDirectives[];
15+
getLoadingDirectives(component: Component, element: HTMLElement | SVGElement): ElementLoadingDirectives[];
1616
private showElement;
1717
private hideElement;
1818
private addClass;

src/LiveComponent/assets/dist/live_controller.js

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,7 +1948,7 @@ class Component {
19481948
}
19491949
}
19501950
this.backendRequest = this.backend.makeRequest(this.valueStore.getOriginalProps(), this.pendingActions, this.valueStore.getDirtyProps(), this.getChildrenFingerprints(), this.valueStore.getUpdatedPropsFromParent(), filesToSend);
1951-
this.hooks.triggerHook('loading.state:started', this.element, this.backendRequest);
1951+
this.hooks.triggerHook('loading.state:started', this.element, this.backendRequest, this);
19521952
this.pendingActions = [];
19531953
this.valueStore.flushDirtyPropsToPending();
19541954
this.isRequestPending = false;
@@ -1995,7 +1995,7 @@ class Component {
19951995
}
19961996
return;
19971997
}
1998-
this.hooks.triggerHook('loading.state:finished', this.element);
1998+
this.hooks.triggerHook('loading.state:finished', this.element, this);
19991999
const modifiedModelValues = {};
20002000
Object.keys(this.valueStore.getDirtyProps()).forEach((modelName) => {
20012001
modifiedModelValues[modelName] = this.valueStore.get(modelName);
@@ -2296,28 +2296,28 @@ class StandardElementDriver {
22962296

22972297
class LoadingPlugin {
22982298
attachToComponent(component) {
2299-
component.on('loading.state:started', (element, request) => {
2300-
this.startLoading(element, request);
2299+
component.on('loading.state:started', (element, request, component) => {
2300+
this.startLoading(component, element, request);
23012301
});
2302-
component.on('loading.state:finished', (element) => {
2303-
this.finishLoading(element);
2302+
component.on('loading.state:finished', (element, component) => {
2303+
this.finishLoading(component, element);
23042304
});
2305-
this.finishLoading(component.element);
2305+
this.finishLoading(component, component.element);
23062306
}
2307-
startLoading(targetElement, backendRequest) {
2308-
this.handleLoadingToggle(true, targetElement, backendRequest);
2307+
startLoading(component, targetElement, backendRequest) {
2308+
this.handleLoadingToggle(component, true, targetElement, backendRequest);
23092309
}
2310-
finishLoading(targetElement) {
2311-
this.handleLoadingToggle(false, targetElement, null);
2310+
finishLoading(component, targetElement) {
2311+
this.handleLoadingToggle(component, false, targetElement, null);
23122312
}
2313-
handleLoadingToggle(isLoading, targetElement, backendRequest) {
2313+
handleLoadingToggle(component, isLoading, targetElement, backendRequest) {
23142314
if (isLoading) {
23152315
this.addAttributes(targetElement, ['busy']);
23162316
}
23172317
else {
23182318
this.removeAttributes(targetElement, ['busy']);
23192319
}
2320-
this.getLoadingDirectives(targetElement).forEach(({ element, directives }) => {
2320+
this.getLoadingDirectives(component, targetElement).forEach(({ element, directives }) => {
23212321
if (isLoading) {
23222322
this.addAttributes(element, ['data-live-is-loading']);
23232323
}
@@ -2401,10 +2401,10 @@ class LoadingPlugin {
24012401
}
24022402
loadingDirective();
24032403
}
2404-
getLoadingDirectives(element) {
2404+
getLoadingDirectives(component, element) {
24052405
const loadingDirectives = [];
24062406
let matchingElements = [...element.querySelectorAll('[data-loading]')];
2407-
matchingElements = matchingElements.filter((elt) => elt.closest('[data-controller~="live"]') === element);
2407+
matchingElements = matchingElements.filter((elt) => elementBelongsToThisComponent(elt, component));
24082408
if (element.hasAttribute('data-loading')) {
24092409
matchingElements = [element, ...matchingElements];
24102410
}

src/LiveComponent/assets/src/Component/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ export default class Component {
145145
* * render:started (html: string, response: BackendResponse, controls: { shouldRender: boolean }) => {}
146146
* * render:finished (component: Component) => {}
147147
* * response:error (backendResponse: BackendResponse, controls: { displayError: boolean }) => {}
148-
* * loading.state:started (element: HTMLElement, request: BackendRequest) => {}
149-
* * loading.state:finished (element: HTMLElement) => {}
148+
* * loading.state:started (element: HTMLElement, request: BackendRequest, component: Component) => {}
149+
* * loading.state:finished (element: HTMLElement, component: Component) => {}
150150
* * model:set (model: string, value: any, component: Component) => {}
151151
*/
152152
on(hookName: string, callback: (...args: any[]) => void): void {
@@ -383,7 +383,7 @@ export default class Component {
383383
this.valueStore.getUpdatedPropsFromParent(),
384384
filesToSend,
385385
);
386-
this.hooks.triggerHook('loading.state:started', this.element, this.backendRequest);
386+
this.hooks.triggerHook('loading.state:started', this.element, this.backendRequest, this);
387387

388388
this.pendingActions = [];
389389
this.valueStore.flushDirtyPropsToPending();
@@ -453,7 +453,7 @@ export default class Component {
453453
// remove the loading behavior now so that when we morphdom
454454
// "diffs" the elements, any loading differences will not cause
455455
// elements to appear different unnecessarily
456-
this.hooks.triggerHook('loading.state:finished', this.element);
456+
this.hooks.triggerHook('loading.state:finished', this.element, this);
457457

458458
/**
459459
* For any models modified since the last request started, grab

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
DirectiveModifier,
44
parseDirectives
55
} from '../../Directive/directives_parser';
6+
import { elementBelongsToThisComponent } from '../../dom_utils';
67
import { combineSpacedArray } from '../../string_utils';
78
import BackendRequest from '../../Backend/BackendRequest';
89
import Component from '../../Component';
@@ -15,33 +16,33 @@ interface ElementLoadingDirectives {
1516

1617
export default class implements PluginInterface {
1718
attachToComponent(component: Component): void {
18-
component.on('loading.state:started', (element: HTMLElement, request: BackendRequest) => {
19-
this.startLoading(element, request);
19+
component.on('loading.state:started', (element: HTMLElement, request: BackendRequest, component: Component) => {
20+
this.startLoading(component, element, request);
2021
});
21-
component.on('loading.state:finished', (element: HTMLElement) => {
22-
this.finishLoading(element);
22+
component.on('loading.state:finished', (element: HTMLElement, component: Component) => {
23+
this.finishLoading(component, element);
2324
});
2425
// hide "loading" elements to begin with
2526
// This is done with CSS, but only for the most basic cases
26-
this.finishLoading(component.element);
27+
this.finishLoading(component, component.element);
2728
}
2829

29-
startLoading(targetElement: HTMLElement|SVGElement, backendRequest: BackendRequest): void {
30-
this.handleLoadingToggle(true, targetElement, backendRequest);
30+
startLoading(component: Component, targetElement: HTMLElement|SVGElement, backendRequest: BackendRequest): void {
31+
this.handleLoadingToggle(component, true, targetElement, backendRequest);
3132
}
3233

33-
finishLoading(targetElement: HTMLElement|SVGElement): void {
34-
this.handleLoadingToggle(false, targetElement, null);
34+
finishLoading(component: Component, targetElement: HTMLElement|SVGElement): void {
35+
this.handleLoadingToggle(component,false, targetElement, null);
3536
}
3637

37-
private handleLoadingToggle(isLoading: boolean, targetElement: HTMLElement|SVGElement, backendRequest: BackendRequest|null) {
38+
private handleLoadingToggle(component: Component, isLoading: boolean, targetElement: HTMLElement|SVGElement, backendRequest: BackendRequest|null) {
3839
if (isLoading) {
3940
this.addAttributes(targetElement, ['busy']);
4041
} else {
4142
this.removeAttributes(targetElement, ['busy']);
4243
}
4344

44-
this.getLoadingDirectives(targetElement).forEach(({ element, directives }) => {
45+
this.getLoadingDirectives(component, targetElement).forEach(({ element, directives }) => {
4546
// so we can track, at any point, if an element is in a "loading" state
4647
if (isLoading) {
4748
this.addAttributes(element, ['data-live-is-loading']);
@@ -148,12 +149,12 @@ export default class implements PluginInterface {
148149
loadingDirective();
149150
}
150151

151-
getLoadingDirectives(element: HTMLElement|SVGElement) {
152+
getLoadingDirectives(component: Component, element: HTMLElement|SVGElement) {
152153
const loadingDirectives: ElementLoadingDirectives[] = [];
153154
let matchingElements = [...element.querySelectorAll('[data-loading]')];
154155

155156
// ignore elements which are inside a nested "live" component
156-
matchingElements = matchingElements.filter((elt) => elt.closest('[data-controller~="live"]') === element);
157+
matchingElements = matchingElements.filter((elt) => elementBelongsToThisComponent(elt, component));
157158

158159
// querySelectorAll doesn't include the element itself
159160
if (element.hasAttribute('data-loading')) {

src/LiveComponent/doc/index.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -889,8 +889,8 @@ The following hooks are available (along with the arguments that are passed):
889889
* ``render:started`` args ``(html: string, response: BackendResponse, controls: { shouldRender: boolean })``
890890
* ``render:finished`` args ``(component: Component)``
891891
* ``response:error`` args ``(backendResponse: BackendResponse, controls: { displayError: boolean })``
892-
* ``loading.state:started`` args ``(element: HTMLElement, request: BackendRequest)``
893-
* ``loading.state:finished`` args ``(element: HTMLElement)``
892+
* ``loading.state:started`` args ``(element: HTMLElement, request: BackendRequest, component: Component)``
893+
* ``loading.state:finished`` args ``(element: HTMLElement, component: Component)``
894894
* ``model:set`` args ``(model: string, value: any, component: Component)``
895895

896896
Loading States

0 commit comments

Comments
 (0)