[英]*ngIf with async pipe for observable from BehaviorSubject seem to activate incorrectly until data is loaded
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. 如果响应具有非空数组,则* ngIf条件将evalutes为true,并且将显示消息, 直到加载数据为止 。
Html template snippet: Html模板代码段:
<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. 该商店使用BehaviourSubject ,它保存来自实际执行HTTP调用的服务的响应。
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. 这样,只有在解析异步调用后,才能有效地处理所有条件和主要内容。
The culprit is the initialisation of the BehaviorSubject with an empty list, which gets emitted and the condition evaluates to true: 罪魁祸首是使用空列表初始化BehaviorSubject,该列表将被释放并且条件的计算结果为true:
private _personalBookmarks: BehaviorSubject<List<Bookmark>> = new BehaviorSubject(List([]));
Fix - init the BehaviorSubject with a null
or undefined
修复 - 使用null
或undefined
初始化BehaviorSubject
private _personalBookmarks: BehaviorSubject<List<Bookmark>> = new BehaviorSubject(null);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.