我有一个 Angular 18 组件,它接收一个可观察对象,我使用管道将其呈现在页面上async
。我希望能够修改此组件内的数据,然后按“保存”按钮。
在按下“保存”按钮之前,如何编辑此组件内的值?我对使用异步管道还有些陌生,通常我只会在组件内订阅,但我试图坚持最佳实践并避免在可能的情况下订阅,而是让异步管道来处理这个问题。
以下是我正在做的事情
export class TimesheetSelectedDayComponent {
private readonly activatedRoute = inject(ActivatedRoute);
private readonly timesheetService = inject(TimesheetService);
//whenever the route params OR the selected timesheet changes...
selectedDay$ = combineLatest({
params$: this.activatedRoute.paramMap,
timesheet$: this.timesheetService.selectedTimesheet$,
}).pipe(
switchMap((results) =>
//now get the matching day from the timesheet
of(results.timesheet$?.days.find((d) => d.date.dayOfWeek === results.params$.get('dayOfWeek'))),
),
);
addAbsence(absence: ITimesheetAbsence): void {
//How do I add this to the selectedDay.absences array?
}
removeAbsence(absenceTimeEntity: ITimesheetAbsence): void {
//How do I remove this from the selectedDay.absences array?
}
}
@if (selectedDay$ | async; as selectedDay) {
<h5 class="card-header">{{ selectedDay.date }}</h5>
<div class="card-body">
<ul class="list-group">
<li class="list-group-item">
<app-time-entity-editor name="Work Day" [timeEntityObject]="selectedDay.workDay" />
</li>
<li class="list-group-item">
<app-time-entity-editor name="Lunch" [timeEntityObject]="selectedDay.lunch" />
</li>
@for (absence of selectedDay.absences; track $index) {
<li class="list-group-item">
<app-time-entity-editor
isRemovable="true"
[name]="absence.name"
[timeEntityObject]="absence"
(removeClick)="removeAbsence($event)"
/>
</li>
}
</ul>
<app-absence-selector class="d-block mt-2" (selectAbsence)="addAbsence($event)" />
</div>
<button type="button" class="btn btn-outline-success btn-lg">Save</button>
</div>
} @else {
<h5 class="card-header"> </h5>
<div class="card-body">
<app-spinner />
</div>
}
基本上,我希望能够在保存更改之前对组件中的数据进行更改,并使可观察对象在订阅的其他区域中做出反应
只需传递
selectedDay
给方法即可。因为removeAbsence
传递索引比传递项目本身更容易。我会尝试这样的事情:
然后改变
到
我很欣赏开发人员努力遵循最佳实践。为此点赞!
你说得对;避免手动处理订阅而使用
async
管道是一种常见做法,或者有些人可能会说是最佳实践。async
管道本质上是在可观察对象可用时订阅它,并在组件被销毁时取消订阅。这就是它流行的原因——它降低了开发人员忘记取消订阅特定值的可能性。我过去一直遵循这种方法,但随着新功能的推出,我现在更喜欢以下选项之一:
1. 使用Angular 信号
您可以利用该
rxjs/interop
toSignal()
函数将可观察对象转换为信号,然后将该信号用于所有任务。以下是示例:请注意,使用
toSignal()
将立即订阅,而不会等待任何条件。但是,根据您的代码,这应该不是问题。此外,仅在注入上下文toSignal()
中才允许。2.使用rxjs:takeUntilDestroyed()
通过将此运算符添加到管道,您可以确保在组件被销毁时取消订阅。这样,您就可以订阅可观察对象而不必担心取消订阅。
请注意,这也需要注入上下文。
3. 手动订阅和取消订阅
如果上述解决方案均不起作用,我将订阅可观察对象并取消订阅
ngOnDestroy()
。但是,在这种情况下,我建议遵循@JSmart523的解决方案。总之,我强烈建议使用 Signals 方法,因为 Angular 正朝着这个方向发展,它确保最佳实践,同时保持项目最新。Angular Signals 还提供其他好处,包括性能优势。
参见: