NativeScript/nativescript-angular

On Android signals are not delivered for pages still residing on the page stack but being covered by another page

Closed this issue · 7 comments

Environment

✔ Getting NativeScript components versions information...
✔ Component nativescript has 8.9.3 version and is up to date.
✔ Component @nativescript/core has 8.9.7 version and is up to date.
✔ Component @nativescript/ios has 8.9.2 version and is up to date.
✔ Component @nativescript/android has 8.9.1 version and is up to date.
"apollo-angular": "11.0.0",
"@angular/animations": "20.1.4",
"@angular/common": "20.1.4",
"@angular/compiler": "20.1.4",
"@angular/core": "20.1.4",
"@angular/forms": "20.1.4",
"@angular/platform-browser": "20.1.4",
"@angular/platform-browser-dynamic": "20.1.4",

Describe the bug
I am observing a problematic behavior on android. When changing a signal value the signal seems to be not evaluated in case a page is covered by another page. I mean, by navigating away from the page and the page is residing on the page stack, no signals seem to be delivered anymore.

What I want to achieve is to trigger a *ngIf to remove a chart on the page when the page was left (needed as redrawing on the covered page results in app crashing on onDeviceOrientationChanged). I do this by subscribing to the page Service
Example:

public _displayChart = signal<boolean>(false)
this._subscription.add(this.pageService.inPage$.subscribe(inPage => {
   this._displayChart.set(inPage);
  // this.cdr.detectChanges()
 })

Expected behavior
I think in order to adopt for the behavior on mobile, I mean pages reside on the page stack rather than being destroyed like when left in the browser, the expected behavior should be that signal changes are propagated when they appear. I also see the issue on effects not being executed when page is left.

A workaround is possible to enforce signal execution via calling change detection manually (commented line ..detectChanges). However, would be nice if not such workarounds would be required.

You're correct, and this is by design. Pages that aren't shown are detached from change detection until they're needed again (back navigation). Does it not update as you navigate back?

@edusperoni : Well it does, but this is too late. When pageService sets inPage to false, the page is detached already. Hence the chart I want to remove will not get removed via the signal change anymore.

I am now wondering, is my workaround save? I mean will detectedChanges() always ensure that detached view signals are evaluated?

I hope this will stay by design. Otherwise I would not have a mechanism to enforce the behaviour anymore.

I am wondering, when is the page marked as detached? Is the page already in detached state when navigatedFrom is being called? Or would it be save to set signals in this callback for them to be immediately evaluated?

Found a working solution without need for calling detect changes and will close the issue. Thanks for your time!

I wonder what solution you used? As of now when the page is navigatedFrom it's detached from CD and on navigatedTo it's attached (these events are all sent to PageService)

@edusperoni
Just wanted to come back on you in regards to the issue, in hope you have an idea how this could be resolved. I am not really finding a sufficient solution for my use case, as signals seem to be evaluated not before the relevant page is visible again. In my use case I have to recreate a view in order to render charts correctly after a orientationChangeEvent has happened. It would be great if signals would be evaluated before the page becomes visible, as the view with the wrong layouts gets visible for a short moment before signal evaluation leads to recreation of the view. See attached video, the top chart on the main page shows the wrong layout for a short time before it is redrawn. Is there any option at which event I could connect my logic to recreate the relevant view before the page is shown? I already tried the usual suspect page events. However, seems like everything I am doing in these events is not propagated before the page is on display

[

Bildschirmaufnahme.2025-08-05.um.19.33.45.mov

](url)

I tried navigatingTo event to recreate the view in case a page rotation has happened and user navigates back to page. However, when changing the signal that removes the view synchronous, the app crashes on android. i therefore wrapped it in setTimeout({},0)
The solution you are seeing in the video is the best I could come up with so far, which used

effect(() => {
  if (this._lastRenderedOrientation() !== this._newOrientation()) {
    this._lastRenderedOrientation.set(this._newOrientation());
    setTimeout(() => {
    this._chartCreated.set(false);
    this.cdr.detectChanges();
    this._chartCreated.set(true);
  });
 }
});

Solution
@directive({ selector: '[ifOrientationChange]' })
export class IfOrientationChangeDirective {
private templateRef = inject(TemplateRef<NsIfContext>);
private viewContainer = inject(ViewContainerRef);
private viewRef?: EmbeddedViewRef;

constructor() {
	this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef, null);
	fromEventPattern(
		handler => Application.on(Application.orientationChangedEvent, handler),
		handler => Application.off(Application.orientationChangedEvent, handler)
	)
		.pipe(takeUntilDestroyed())
		.subscribe(() => {
			this.viewRef?.destroy();
			this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef, null);
			this.viewRef.detectChanges();  // needed if orientation happens while element is on detached page
		});
}

}