我有一个Angular组件,其BehaviourSubject初始化为当前月份:
textLabel: string;
private monthIndex$: BehaviorSubject<number>;
private MONTHS = [
"Gennaio",
"Febbraio",
"Marzo",
"Aprile",
"Maggio",
"Giugno",
"Luglio",
"Agosto",
"Settembre",
"Ottobre",
"Novembre",
"Dicembre"
];
constructor(private listService: ShoppingListService) {}
ngOnInit() {
this.monthIndex$ = new BehaviorSubject<number>(new Date().getMonth());
// Like this it does not display the label
this.setMonthLabel(this.monthIndex$.value);
this.model$ = this.monthIndex$.pipe(
switchMap((monthValue: number) => {
// this.setMonthLabel(monthValue); // This way it works!
return this.listService.getHistoryChartModel(monthValue);
}),
takeUntil(this.destroy$)
);
}
private setMonthLabel(monthIndex: number) {
this.textLabel = this.MONTHS[monthIndex];
}
setMonth(direction: number) {
let monthIndex = this.monthIndex$.getValue();
monthIndex += direction;
monthIndex =
monthIndex < 0 ? 0 : monthIndex > 11 ? 11 : monthIndex;
this.monthIndex$.next(monthIndex);
this.setMonthLabel(monthIndex);
}
和模板:
<div class="view-sel-container">
<button
color="primary" mat-icon-button
(click)="setMonth(-1)"
[disabled]="monthIndex === 0">
<i class="material-icons">
keyboard_arrow_left
</i>
</button>
<span class="label-text" *ngIf="textLabel">{{ textLabel }}</span>
<button
color="primary" mat-icon-button
(click)="setMonth(1)"
[disabled]="monthIndex === 11">
<i class="material-icons">
keyboard_arrow_right
</i>
</button>
是否由于将BehavourSubject值传递给方法this.setMonthLabel(this.monthIndex$.value)
而导致标签未显示在模板中的时间原因?
更新
Deborah Kurata使用get / set而不是BehaviourSubject提供的解决方案是最好的方法。我将原始问题/代码保持打开状态,因为仍然无法通过传递behaviourSubject值作为参数来理解为什么代码现在可以正常工作。
答案 0 :(得分:1)
考虑使用不需要Subject
或BehaviorSubject
的类似内容:
组件
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
@Component({
templateUrl: './history-chart.component.html'
})
export class HistorChartComponent {
textLabel: string;
model$: Observable<any>;
private _monthIndex: number;
get monthIndex(): number {
return this._monthIndex;
}
set monthIndex(value: number) {
console.log("setter called with: " + value);
// Set the label
this.setMonthLabel(value);
// Get the data
this.getMonthData(value);
this._monthIndex = value;
}
private MONTHS = [
"Gennaio",
"Febbraio",
"Marzo"
];
constructor() { }
ngOnInit() {
// This calls the setter
this.monthIndex = new Date().getMonth();
}
// Increment or decrement the month index
// This calls the setter
setMonth(value: number) {
this.monthIndex += value;
}
private setMonthLabel(monthIndex: number) {
this.textLabel = this.MONTHS[monthIndex];
}
private getMonthData(monthIndex: number): void {
// Commented out because I don't have the service code
//this.model$ = this.listService.getHistoryChartModel(monthIndex);
// Faking out the call to the service
this.model$ = of(
{ id: 1, value: "some data for month : " + this.MONTHS[monthIndex] },
);
}
}
每次用户更改值或在代码中更改值时,都会自动调用设置器。因此,setter是执行任何需要响应更改的代码的好地方。
使用上面的代码,每当用户单击任意一个按钮时,就会在ngOnInt上检索月份数据。如果您在提供的stackblitz中没有看到此行为,请告诉我。
模板
<div class="view-sel-container">
<button
color="primary" mat-icon-button
(click)="setMonth(-1)"
[disabled]="monthIndex === 0">
<i class="material-icons">
keyboard_arrow_left
</i>
</button>
<span class="label-text" *ngIf="textLabel">{{ textLabel }}</span>
<button
color="primary" mat-icon-button
(click)="setMonth(1)"
[disabled]="monthIndex === 11">
<i class="material-icons">
keyboard_arrow_right
</i>
</button>
<div>
<span class="label-text" *ngIf="textLabel">
{{textLabel}}
</span>
</div>
<div *ngIf="(model$ | async) as model">
<div>
{{ model.value }}
</div>
</div>
这是相关的堆叠闪电战:https://stackblitz.com/edit/angular-bpusk2
答案 1 :(得分:0)
this.monthIndex$ = new BehaviorSubject<number>(new Date().getMonth());
// Like this it does not display the label
this.setMonthLabel(this.monthIndex$.value);
this.model$ = this.monthIndex$.pipe(
tap(monthValue => {
this.setMonthLabel(monthValue);
return this.listService.getHistoryChartModel(monthValue);
}),
takeUntil(this.destroy$)
);
this.setMonthLabel(this.monthIndex$.value)
?this.setMonthLabel
的作用是什么?