I am currently using Angular 13 and Ionic v6 with AngularFire v7.
After logging in to the application with firebase authentication. 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. 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.
I have tried to manually detect changes and tried multiple versions of observables and strategies but nothing works.
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
<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
<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
Resume: There was a bug in @ionic/angular and you have to update it:
npm i @ionic/angular@latest
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.