If the array in response is empty I want to display a message, otherwise the elements of the array.
In case the response has a non-empty array the *ngIf condition evalutes to true and the message is displayed until the data is loaded.
Html template snippet:
<div *ngIf="personalAndStarredBookmarks$ && (personalAndStarredBookmarks$ | async)?.size === 0; else personalBookmarksList" class="missing-category-bookmarks-message alert alert-info">
<p>No bookmarks yet</p>
</div>
<ng-template #personalBookmarksList>
<app-async-bookmark-list [bookmarks]="personalAndStarredBookmarks$" [shownSize]="10" [userData]="userData"></app-async-bookmark-list>
</ng-template>
Component snippet:
import { List } from 'immutable';
export class PersonalBookmarksListComponent implements OnInit {
personalAndStarredBookmarks$: Observable<List<Bookmark>>;
ngOnInit(): void {
this.personalAndStarredBookmarks$ = this.personalBookmarksStore.getPersonalBookmarks();
}
...
}
The store uses a BehaviourSubject where it holds the response from a service that actually does the HTTP call.
Store snippet
@Injectable()
export class PersonalBookmarksStore {
private _personalBookmarks: BehaviorSubject<List<Bookmark>> = new BehaviorSubject(List([]));
constructor(private personalBookmarkService: PersonalBookmarkService,
private keycloakService: KeycloakService
) {
keycloakService.loadUserProfile().then(keycloakProfile => {
this.userId = keycloakProfile.id;
this.loadInitialData();
});
}
private loadInitialData() {
this.personalBookmarkService.getAllPersonalBookmarks(this.userId)
.subscribe(
data => {
let bookmarks: Bookmark[] = <Bookmark[]>data;
this._personalBookmarks.next(List(bookmarks));
},
err => console.error('Error retrieving bookmarks', err)
);
}
getPersonalBookmarks(): Observable<List<Bookmark>> {
return this._personalBookmarks.asObservable();
}
...
}
If I am calling directly the Service (not the Store) in the component it behaves as expected...
You should restructure your template to handle the async calls efficiently by assigning a local variable as
<ng-content*ngIf="personalAndStarredBookmarks$ | async as personalAndStarredBookmarks">
<div *ngIf="personalAndStarredBookmarks.size === 0; else personalBookmarksList"
class="missing-category-bookmarks-message alert alert-info">
<p>No bookmarks yet</p>
</div>
<ng-template #personalBookmarksList>
<app-async-bookmark-list [bookmarks]="personalAndStarredBookmarks" [shownSize]="10"
[userData]="userData">
</app-async-bookmark-list>
</ng-template>
<ng-content>
With this, you can efficiently handle all the conditions and the main content loads only after the async call is resolved.
See a DEMO HERE
The culprit is the initialisation of the BehaviorSubject with an empty list, which gets emitted and the condition evaluates to true:
private _personalBookmarks: BehaviorSubject<List<Bookmark>> = new BehaviorSubject(List([]));
Fix - init the BehaviorSubject with a null
or undefined
private _personalBookmarks: BehaviorSubject<List<Bookmark>> = new BehaviorSubject(null);
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.