While working on my Angular web application, I encountered an issue with displaying data when using Observables and Subjects. Typically, when searching the Firebase DB, I use
*ngFor="let myvar of _myvar | async"
in my HTML to display the retrieved data. However, whenever a Subject comes into play, the data is not displayed until I interact with an element on the page.Below is the code snippet where the problem occurs:
<section>
<div id="paddingTop" fxLayout="row" fxLayout.lt-md="column" fxLayoutAlign="space-around center">
<div>
<h2>*****************</h2>
<mat-icon>place</mat-icon>
<mat-form-field color="accent" appearance="fill" id="searchAddress">
<mat-label>*****************</mat-label>
<input
matInput
ngx-google-places-autocomplete #placesRef="ngx-places"
(onAddressChange)="handleAddressChange($event)" />
<button mat-button *ngIf="address" matSuffix mat-icon-button aria-label="Clear" (click)="address=''">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
</div>
</div>
<div id="searchPart">
<h2>*****************</h2>
<section class="mobile" fxLayout="column" fxLayoutAlign="center center" fxLayoutGap="20px" fxHide.lg *ngFor="let id of _feedersId | async">
<app-feeder-card
[feederId] = "id"
[clientId] = "this.uid"
></app-feeder-card>
</section>
<section *ngIf="feedersId.length == 0" fxLayout="column" fxLayoutAlign="center center" >
<p>*****************</p>
<p>
<mat-icon>arrow_upward</mat-icon>
*****************
<mat-icon>arrow_upward</mat-icon>
</p>
</section>
</div>
</section>
home.component.ts
import { Component, OnInit } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { Router } from '@angular/router';
import { Observable, Subject } from 'rxjs';
import { AuthService } from 'src/app/auth/auth.service';
import { Order } from 'src/app/order/order.model';
import { User } from '../user.model';
@Component({
selector: 'app-user-home',
templateUrl: './user-home.component.html',
styleUrls: ['./user-home.component.scss']
})
export class UserHomeComponent implements OnInit {
orders: Observable<Order[]>;
feedersId: Array<string> = [];
_feedersId: Observable<Array<string>> = this.getFeederArray();
uid: string;
constructor(private router: Router, private authService: AuthService, private db: AngularFirestore) {}
ngOnInit(): void {
this.getFeederArray().subscribe(r => {
console.log('tests')
this.setFeederId(r);
})
}
address = '';
public handleAddressChange(address: any) {
console.log(address);
this.address = address.formatted_address;
const lat = address.geometry.location.lat();
const lng = address.geometry.location.lng();
const adrs = address.formatted_address;
this.router.navigate(['/search-feeder/', lat, lng, adrs]);
}
getUser(): Observable<User> {
return this.authService.getUser().switchMap(user => {
this.uid = user.uid;
return this.db.collection('user').doc(user.uid).valueChanges({ idField: 'id' }) as Observable<User>;
}).map(response => {
return response;
});
}
getFeederArray(): Observable<Array<string>> {
let toReturn: Array<string> = [];
var subject = new Subject<Array<string>>();
this.getUser().subscribe(user => {
this.orders = this.db.collection("orders", ref => {
return ref
.where("clientId", "==", user.id)
}).valueChanges({ idField: 'id' }) as Observable<Order[]>;
this.orders.subscribe(orders => {
orders.forEach(order => {
if(toReturn.indexOf(order.feederId) == -1) {
toReturn.push(order.feederId);
}
})
})
subject.next(toReturn);
})
return subject.asObservable();
}
setFeederId(ids: Array<string>) {
this.feedersId = ids;
}
}