在一开始我想写我不知道很好的Angular 和我困惑与我的问题。在我的应用程序中,我有一个大的组件称为ScheduleComponent,其中包括在顶部会议收集和底部3个组件,根据用户的行动而改变(CreateScheduleComponent,SuccessComponent,ScheduleComponent和CreateScheduleComponent正在使用来自公共服务(如ScheduleService)的名为会议的BehaviorSubject对象。
问题出在我的CreateScheduleComponent上,因为在构造函数中,我从会议的公共服务订阅了可观察的会议$ object,在同一个组件中,我使用方法创建新的会议,在这个方法中,我必须发出新的值,因为我的ScheduleComponent也订阅了会议$ object,我想看到我的会议集合中的所有更改(cancel,add),但这会触发我在(ScheduleComponent和CreateScheduleComponent)中的所有订阅,我想阻止CreateScheduleComponent中的订阅。
请告诉我,我该如何解决这个问题。
export class ScheduleComponent {
meetings$: Observable<Meetings[]> = this.scheduleSvc.meetings$;
constructor(private scheduleSvc: ScheduleService, private userTokenSvc: UserTokenService, private router : Router) {
this.scheduleSvc.getMeetings()
.subscribe(rs => {
let meetings = rs.filter(meeting => meeting.clientId == this.userTokenSvc.getUser().id && meeting.isScheduled);
this.scheduleSvc.addMeetings(meetings); <- Im not sure about this line
});
}
hasCreateScheduleBtn(){
return this.router.url == this.router.createUrlTree(['/schedule']).toString();
}
cancelMeeting(meetingId: number): void{
this.scheduleSvc.cancelMeeting(meetingId)
.subscribe(rs => this.meetings$ = this.meetings$.pipe(map(meetings => meetings.filter(meeting => meeting.id !== meetingId))));
}
}
ScheduleComponent.html
<div>
<div class="text-title">
Schedule
</div>
<div class="schedule-info-box">
<div class="schedule-info-text">Your scheduled meetings</div>
<div>
<div class="schedule-box" *ngFor="let meeting of meetings$ | async">
<pre style="display:contents;">{{ meeting.startMeetingDate }} {{ meeting.meetingTopic }}</pre>
<button class="cancel-schedule-btn" (click)="cancelMeeting(meeting.id)" [hidden]="!meeting.isScheduled">CANCEL</button>
</div>
</div>
</div>
<button class="create-schedule-btn" *ngIf="hasCreateScheduleBtn()" routerLink="/schedule/create">
CREATE MEETING
</button>
<router-outlet></router-outlet>
</div>
CreateScheduleComponent
export class CreateScheduleComponent{
@ViewChild('dateInput', { static: true }) dateInput: ElementRef;
@ViewChild('matSelectTime', { static: true }) matSelectTime: MatSelect;
@ViewChild('matSelect', { static: true }) topicSelect: MatSelect;
times = TIME_INFO;
topics = TOPICS;
createResultLink: string;
meetingDate: any[] = [];
meetings: Meetings[];
constructor(public scheduleSvc: ScheduleService, private router: Router, public datePipe: DatePipe) {
this.scheduleSvc.meetings$
.pipe(first()) <- only first() prevents triggers after next
.subscribe(x =>
{
this.meetings = x;
this.createMeetingDates(x);
});
}
createMeeting() {
let dividedTime = this.matSelectTime.value.split(':') as number[];
let date = new Date(this.datePipe.transform(this.dateInput.nativeElement.value) as string);
let meeting =
{
createDate: new Date(),
clientId: 14,
startMeetingDate: new Date(date.getFullYear(), date.getMonth(), date.getDate(), dividedTime[0], dividedTime[1], 0),
meetingTopic: this.topicSelect.value,
isScheduled: true
};
this.scheduleSvc.createMeeting(meeting)
.pipe(
switchMap(x =>
{
this.createResultLink = '/schedule/success';
this.scheduleSvc.addMeeting(meeting as Meetings);
return of(x);
}),
catchError(_ => this.createResultLink = '/schedule/error'))
.subscribe(x => this.router.navigate([this.createResultLink]));
}
日程服务
export class ScheduleService {
private meetingsSource = new BehaviorSubject<Meetings[]>([]);
meetings$ = this.meetingsSource.asObservable();
constructor(private httpClient: HttpClient) {
}
getMeetings(): Observable<Meetings[]> {
return this.httpClient.get<Meetings[]>(`${baseUrl}/api/schedule/meetings`, httpOptions);
}
createMeeting(meeting: any): Observable<any> {
return this.httpClient.post(`${baseUrl}/api/schedule/createMeeting`, meeting, { responseType: 'text' })
}
addMeetings(meetings: Meetings[]){
this.meetingsSource.next(meetings);
}
addMeeting(meeting: Meetings) {
const currentValue = this.meetingsSource.value;
const updatedValue = [...currentValue, meeting];
this.meetingsSource.next(updatedValue);
}
}
1条答案
按热度按时间6ojccjat1#
如果我理解正确的话,这里的问题是
CreateScheduleComponent
在页面重定向到成功组件之前显示了新创建的会议的一个flash。如果是这个问题,您可以做的是在成功创建新会议时强制取消订阅
scheduleSvc.meetings$
,从而防止执行订阅回调。为此,您可以在
CreateScheduleComponent
中创建一个RxJS Subject,名称类似于meetingAdded$
:然后,在
scheduleSvc.meetings$
管道中,使用takeUntil operator在meetingAdded$
发出以下命令时强制取消订阅:然后,在
createMeeting
流中,使用tap operator触发meetingAdded$
的emit,它用于副作用:有了这些部分,一旦添加了会议,组件就应该取消订阅
meetings$
,因此不会显示新添加的会议。