From a3cd204f616606ccffc35082655e55fdfb19fe28 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Wed, 29 Nov 2023 16:53:33 -0500 Subject: [PATCH] fix(overlays): trigger is configured on load (#28526) Issue number: resolves #28524 --------- ## What is the current behavior? Watchers in Stencil are constructed sometime between `connectedCallback` and `componentDidLoad`. If a property is set/changed during that time it is possible for the callback associated with the watcher to not fire because the watcher has not been setup yet. This is most often with `dist-custom-elements` and frameworks such as Angular when using a binding (i.e. `[trigger]` instead of `trigger`) ## What is the new behavior? - The trigger callback associated with the watcher is manually called in `componentDidLoad` for each overlay. ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information Dev build: `7.5.5-dev.11699974376.13a15397` Note: This is a timing related bug due to a behavior in Stencil, so I did not write automated tests. However, I manually verified that this issue a) reproduces on `main` and b) is fixed with this dev build for each overlay component. --- core/src/components/action-sheet/action-sheet.tsx | 11 +++++++++++ core/src/components/alert/alert.tsx | 11 +++++++++++ core/src/components/loading/loading.tsx | 11 +++++++++++ core/src/components/modal/modal.tsx | 11 +++++++++++ core/src/components/picker/picker.tsx | 11 +++++++++++ core/src/components/popover/popover.tsx | 11 +++++++++++ core/src/components/toast/toast.tsx | 11 +++++++++++ 7 files changed, 77 insertions(+) diff --git a/core/src/components/action-sheet/action-sheet.tsx b/core/src/components/action-sheet/action-sheet.tsx index 813e38c7f9..984e24cdaa 100644 --- a/core/src/components/action-sheet/action-sheet.tsx +++ b/core/src/components/action-sheet/action-sheet.tsx @@ -337,6 +337,17 @@ export class ActionSheet implements ComponentInterface, OverlayInterface { if (this.isOpen === true) { raf(() => this.present()); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } render() { diff --git a/core/src/components/alert/alert.tsx b/core/src/components/alert/alert.tsx index 4568e45a38..90a1c281bb 100644 --- a/core/src/components/alert/alert.tsx +++ b/core/src/components/alert/alert.tsx @@ -376,6 +376,17 @@ export class Alert implements ComponentInterface, OverlayInterface { if (this.isOpen === true) { raf(() => this.present()); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } /** diff --git a/core/src/components/loading/loading.tsx b/core/src/components/loading/loading.tsx index 0892b082d1..05e40669d9 100644 --- a/core/src/components/loading/loading.tsx +++ b/core/src/components/loading/loading.tsx @@ -225,6 +225,17 @@ export class Loading implements ComponentInterface, OverlayInterface { if (this.isOpen === true) { raf(() => this.present()); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } disconnectedCallback() { diff --git a/core/src/components/modal/modal.tsx b/core/src/components/modal/modal.tsx index 3c8a091901..ef6114b18b 100644 --- a/core/src/components/modal/modal.tsx +++ b/core/src/components/modal/modal.tsx @@ -368,6 +368,17 @@ export class Modal implements ComponentInterface, OverlayInterface { raf(() => this.present()); } this.breakpointsChanged(this.breakpoints); + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } /** diff --git a/core/src/components/picker/picker.tsx b/core/src/components/picker/picker.tsx index 19d03d2f8b..4232288919 100644 --- a/core/src/components/picker/picker.tsx +++ b/core/src/components/picker/picker.tsx @@ -209,6 +209,17 @@ export class Picker implements ComponentInterface, OverlayInterface { if (this.isOpen === true) { raf(() => this.present()); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } /** diff --git a/core/src/components/popover/popover.tsx b/core/src/components/popover/popover.tsx index 75e16ad70d..21dce20a5d 100644 --- a/core/src/components/popover/popover.tsx +++ b/core/src/components/popover/popover.tsx @@ -370,6 +370,17 @@ export class Popover implements ComponentInterface, PopoverInterface { this.dismiss(undefined, undefined, false); }); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.configureTriggerInteraction(); } /** diff --git a/core/src/components/toast/toast.tsx b/core/src/components/toast/toast.tsx index b7945400b5..0a4fc420fc 100644 --- a/core/src/components/toast/toast.tsx +++ b/core/src/components/toast/toast.tsx @@ -288,6 +288,17 @@ export class Toast implements ComponentInterface, OverlayInterface { if (this.isOpen === true) { raf(() => this.present()); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } /**