[英]Angular Change Detection not happening on Lazy loaded pages on initial navigation
I am currently using Angular 13 and Ionic v6 with AngularFire v7.我目前正在使用 Angular 13 和 Ionic v6 以及 AngularFire v7。
After logging in to the application with firebase authentication.使用 firebase 身份验证登录应用程序后。 I navigate the user to the lazy-loaded home page.
我将用户导航到延迟加载的主页。 In the background, I retrieve some required company data and share them through the service using a behaviour subject.
在后台,我检索了一些所需的公司数据,并使用行为主题通过服务共享它们。 If the user has never logged in before the page gets stuck on loading.
如果用户在页面卡在加载之前从未登录过。
If I resize the window the content appears or if I navigate away and come back the content appears.如果我调整 window 的大小,内容就会出现,或者如果我离开并返回,内容就会出现。 This happens with each lazy-loaded page after initial login.
在初始登录后,每个延迟加载的页面都会发生这种情况。 I use the async pipe to access the observables so all that is managed by angular.
我使用异步 pipe 来访问可观察对象,因此所有这些都由 angular 管理。
I have tried to manually detect changes and tried multiple versions of observables and strategies but nothing works.我曾尝试手动检测更改并尝试了多个版本的可观察对象和策略,但没有任何效果。
Here is a demo of the issue这是问题的演示
Ts file文件
import { Component, OnInit } from '@angular/core';
import { IonRouterOutlet } from '@ionic/angular';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { AddEstimatePage } from './add-estimate/add-estimate.component';
import { Company } from '../models/company.model';
import { MasterService } from '../services/master.service';
import { Estimate } from '../models/estimate.model';
@Component({
selector: 'app-estimates',
templateUrl: './estimates.page.html',
})
export class EstimatesPage implements OnInit {
estimates$: Observable<Estimate[] | any>;
company$: Observable<Company>;
user$: Observable<any>;
isLoading = true;
constructor(private masterSvc: MasterService) {
this.company$ = this.masterSvc.auth().company$;
this.user$ = this.masterSvc.auth().user$;
}
ngOnInit() {
this.init();
}
async editEstimate(
estimate: Estimate,
data: { company: Company; user: any }
) {
const modal = await this.masterSvc.modal().create({
component: AddEstimatePage,
componentProps: {
company: data.company,
user: data.user,
estimate,
isEdit: true,
},
showBackdrop: false,
id: 'editEstimate',
cssClass: 'fullscreen',
});
return await modal.present();
}
async addEstimate(data: { company: Company; user: any }) {
const modal = await this.masterSvc.modal().create({
component: AddEstimatePage,
componentProps: {
company: data.company,
user: data.user,
},
cssClass: 'fullscreen',
showBackdrop: false,
id: 'addEstimate',
});
return await modal.present();
}
init() {
this.estimates$ = this.company$.pipe(
switchMap((company) => {
if (company) {
return this.masterSvc
.edit()
.getDocsByCompanyIdOrdered(
`company/${company.id}/estimates`,
'date',
'desc'
);
} else {
return of(false);
}
})
) as Observable<any>;
}
}
html file html 文件
<app-header title="Estimates" btnName="refresh" (updated)="init()"></app-header>
<ion-content fullscreen="true">
<app-header-condensed title="Estimates"></app-header-condensed>
<ng-container *ngIf="{company: company$ |async, user: user$ | async} as data">
<app-estimate-table
[value]="estimates$"
*ngIf="estimates$ | async else loading"
(selectedItem)="editEstimate($event,data)"
></app-estimate-table>
<ion-fab class="m-2" vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button (click)="addEstimate(data)">
<ion-icon name="add"></ion-icon>
</ion-fab-button>
</ion-fab>
<ng-template #loading>
<div class="ion-padding">
<app-skeleton-text></app-skeleton-text>
<app-skeleton-text></app-skeleton-text>
<app-skeleton-text></app-skeleton-text>
<app-skeleton-text></app-skeleton-text>
</div>
</ng-template>
</ng-container>
</ion-content>
Update更新
I got it working with the following.我得到它与以下工作。 It's a bit questionable but it works:)
这有点可疑,但它有效:)
Ts file文件
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { Observable, of, timer } from 'rxjs';
import { concatMap, filter, switchMap, tap } from 'rxjs/operators';
import { SiteFormComponent } from '../components/site-form/site-form.component';
import { AddEstimatePage } from '../estimates/add-estimate/add-estimate.component';
import { Company } from '../models/company.model';
import { Estimate } from '../models/estimate.model';
import { Site } from '../models/site.model';
import { MasterService } from '../services/master.service';
import { AddSiteComponent } from './add-site/add-site.component';
@Component({
selector: 'app-sites',
templateUrl: './sites.page.html',
})
export class SitesPage implements OnInit {
sites$: Observable<Site[] | any>;
company$: Observable<Company>;
user$: Observable<any>;
isLoading = true;
constructor(
private masterSvc: MasterService,
private change: ChangeDetectorRef
) {
this.company$ = this.masterSvc.auth().company$;
this.user$ = this.masterSvc.auth().user$;
}
ngOnInit() {
this.init();
}
async viewSite(siteData: Site, data: { company: Company; user: any }) {
const modal = await this.masterSvc.modal().create({
component: AddSiteComponent,
componentProps: {
company: data.company,
user: data.user,
siteData,
isEdit: true,
},
showBackdrop: false,
id: 'editSite',
cssClass: 'fullscreen',
});
return await modal.present();
}
async addSite(data: { company: Company; user: any }) {
const modal = await this.masterSvc.modal().create({
component: AddSiteComponent,
componentProps: {
company: data.company,
user: data.user,
isCreate: true,
},
cssClass: 'fullscreen',
showBackdrop: false,
id: 'addSite',
});
return await modal.present();
}
init() {
this.sites$ = this.company$.pipe(
switchMap((company) => {
if (company) {
return this.masterSvc
.edit()
.getDocsByCompanyIdOrdered(
`company/${company.id}/sites`,
'code',
'desc'
)
.pipe(
tap(() => {
this.isLoading = false;
this.change.detectChanges();
})
);
} else {
return timer(1);
}
})
) as Observable<any>;
}
}
html file html 文件
<app-header title="Sites" btnName="refresh" (updated)="init()"></app-header>
<ion-content fullscreen="true">
<app-header-condensed title="Sites"></app-header-condensed>
<ng-container
*ngIf="{company: company$ |async, user: user$ | async,sites: sites$ | async} as data"
>
<app-site-table
[value]="sites$"
*ngIf="!isLoading else loading"
(selectedItem)="viewSite($event,data)"
></app-site-table>
<ion-fab class="m-2" vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button (click)="addSite(data)">
<ion-icon name="add"></ion-icon>
</ion-fab-button>
</ion-fab>
<ng-template #loading>
<div class="ion-padding">
<app-skeleton-text></app-skeleton-text>
<app-skeleton-text></app-skeleton-text>
<app-skeleton-text></app-skeleton-text>
<app-skeleton-text></app-skeleton-text>
</div>
</ng-template>
</ng-container>
</ion-content>
Yesterday I have handled this problem and you can find a complete description on github.com/ionic-team昨天我已经处理了这个问题,你可以在github.com/ionic-team上找到完整的描述
Resume: There was a bug in @ionic/angular and you have to update it:简历:@ionic/angular 有一个错误,你必须更新它:
npm i @ionic/angular@latest
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.