Angular Router.navigate() 上未触发更改检测
Angular Change Detection not triggering on Router.navigate()
我在 Angular 中有一个名为 NewEventComponent
的组件,它只包含一个用于提交新事件的表单。在它的提交方法上它有这个代码:
onSubmit() {
this.isSendingRequest = true;
this.geolocationService.geocodeAddress(this.location.value).subscribe(
(results: google.maps.GeocoderResult[]) => {
if (results && results.length) {
const eventData: EventData = {
name: this.name.value,
location: [results[0].geometry.location.lat(), results[0].geometry.location.lng()],
startDate: this.datetimeService.convertDateAndTimeToISOString(this.startDate.value, this.startTime.value),
endingDate: this.datetimeService.convertDateAndTimeToISOString(this.endingDate.value, this.endingTime.value),
description: this.description.value,
sport: this.sport.value,
intensity: this.intensity.value,
fee: this.fee.value,
maxPlayers: this.maxPlayers.value
};
this.eventService.createEvent(eventData).subscribe(
(res: any) => {
this.alertService.createAlert({ message: EVENT_CREATED_MESSAGE, type: AlertType.Success });
this.router.navigate(['events', res.data.event.id]);
}
);
} else {
this.handleInvalidLocationError();
}
}
);
}
它只是将事件发送到服务器并重定向到事件页面,即EventDetails
组件。该组件仅向服务器请求请求的事件并将其作为输入传递给子组件。这是代码:
TS:
@Component({
selector: 'app-event-details',
templateUrl: './event-details.component.html',
styleUrls: ['./event-details.component.scss']
})
export class EventDetailsComponent implements OnInit {
private event: EventResponse;
constructor(
private activatedRoute: ActivatedRoute,
private eventService: EventService
) { }
ngOnInit() {
this.getEvent();
}
getEvent(): void {
this.activatedRoute.params.subscribe(
(params: Params) => {
this.eventService.getEvent(params.id).subscribe(
(res: any) => {
this.event = res.data.event;
}
);
}
);
}
}
HTML:
<div class="row">
<div class="col">
<div class="info-wrapper">
<app-event-details-info [event]="event">
</app-event-details-info>
</div>
</div>
</div>
而子组件 EventDetailsInfo
仅像这样 @Input() event: EventResponse;
接收事件作为输入,并在 html 中显示信息,如下所示: <h5>{{ event?.name }}</h5>
.
这里的问题是,当从 NewEvent
组件导航到 EventDetails
组件时,不会触发更改检测,所以直到我单击 DOM 中的任意位置,更改未显示。但是当我直接通过 url 导航到 EventDetails
组件时,页面正在正确呈现。
我在变更检测中遗漏了什么?任何的想法?谢谢!
PS:EventService
只执行 HTTP 调用并且 return 它们作为 Observables,比如:
createEvent(eventData: EventData): Observable<any> {
return this.http.post(`${environment.apiUrl}/events/`, eventData);
}
getEvent(eventId: string): Observable<any> {
return this.http.get(`${environment.apiUrl}/events/${eventId}`);
}
PS2:这是'onSubmit()'方法中使用的GeolocationService
方法:
geocodeAddress(address: string): Observable<google.maps.GeocoderResult[]> {
const response: Subject<google.maps.GeocoderResult[]>
= new Subject<google.maps.GeocoderResult[]>();
const request: google.maps.GeocoderRequest = { address };
this.geocoder.geocode(request,
(results: google.maps.GeocoderResult[]) => {
response.next(results);
}
);
return response;
}
更新
onSubmit() {
this.isSendingRequest = true;
this.geolocationService.geocodeAddress(this.location.value).subscribe(
(results: google.maps.GeocoderResult[]) => {
this.zone.run(() => π
if (results && results.length) {
const eventData: EventData = {
name: this.name.value,
location: [results[0].geometry.location.lat(), results[0].geometry.location.lng()],
startDate: this.datetimeService.convertDateAndTimeToISOString(this.startDate.value, this.startTime.value),
endingDate: this.datetimeService.convertDateAndTimeToISOString(this.endingDate.value, this.endingTime.value),
description: this.description.value,
sport: this.sport.value,
intensity: this.intensity.value,
fee: this.fee.value,
maxPlayers: this.maxPlayers.value
};
this.eventService.createEvent(eventData).subscribe(
(res: any) => {
this.alertService.createAlert({ message: EVENT_CREATED_MESSAGE, type: AlertType.Success });
this.router.navigate(['events', res.data.event.id]);
}
);
} else {
this.handleInvalidLocationError();
}
}
});
);
}
原创
也许事件是在 Angular 区域之外发出的。
尝试:
constructor(private zone: NgZone) { }
和:
this.zone.run(() => this.router.navigate(['events', res.data.event.id]));
如果这能解决问题,您应该修复 EventService
根据订阅发生的顺序,您可能会完全错过该活动。考虑使用 shareReplay(1)
并公开一个事件。
或者,将事件的订阅移至构造函数:
constructor(
private activatedRoute: ActivatedRoute,
private eventService: EventService
) {
this.getEvent();
}
ngOnInit() {
}
我在 Angular 中有一个名为 NewEventComponent
的组件,它只包含一个用于提交新事件的表单。在它的提交方法上它有这个代码:
onSubmit() {
this.isSendingRequest = true;
this.geolocationService.geocodeAddress(this.location.value).subscribe(
(results: google.maps.GeocoderResult[]) => {
if (results && results.length) {
const eventData: EventData = {
name: this.name.value,
location: [results[0].geometry.location.lat(), results[0].geometry.location.lng()],
startDate: this.datetimeService.convertDateAndTimeToISOString(this.startDate.value, this.startTime.value),
endingDate: this.datetimeService.convertDateAndTimeToISOString(this.endingDate.value, this.endingTime.value),
description: this.description.value,
sport: this.sport.value,
intensity: this.intensity.value,
fee: this.fee.value,
maxPlayers: this.maxPlayers.value
};
this.eventService.createEvent(eventData).subscribe(
(res: any) => {
this.alertService.createAlert({ message: EVENT_CREATED_MESSAGE, type: AlertType.Success });
this.router.navigate(['events', res.data.event.id]);
}
);
} else {
this.handleInvalidLocationError();
}
}
);
}
它只是将事件发送到服务器并重定向到事件页面,即EventDetails
组件。该组件仅向服务器请求请求的事件并将其作为输入传递给子组件。这是代码:
TS:
@Component({
selector: 'app-event-details',
templateUrl: './event-details.component.html',
styleUrls: ['./event-details.component.scss']
})
export class EventDetailsComponent implements OnInit {
private event: EventResponse;
constructor(
private activatedRoute: ActivatedRoute,
private eventService: EventService
) { }
ngOnInit() {
this.getEvent();
}
getEvent(): void {
this.activatedRoute.params.subscribe(
(params: Params) => {
this.eventService.getEvent(params.id).subscribe(
(res: any) => {
this.event = res.data.event;
}
);
}
);
}
}
HTML:
<div class="row">
<div class="col">
<div class="info-wrapper">
<app-event-details-info [event]="event">
</app-event-details-info>
</div>
</div>
</div>
而子组件 EventDetailsInfo
仅像这样 @Input() event: EventResponse;
接收事件作为输入,并在 html 中显示信息,如下所示: <h5>{{ event?.name }}</h5>
.
这里的问题是,当从 NewEvent
组件导航到 EventDetails
组件时,不会触发更改检测,所以直到我单击 DOM 中的任意位置,更改未显示。但是当我直接通过 url 导航到 EventDetails
组件时,页面正在正确呈现。
我在变更检测中遗漏了什么?任何的想法?谢谢!
PS:EventService
只执行 HTTP 调用并且 return 它们作为 Observables,比如:
createEvent(eventData: EventData): Observable<any> {
return this.http.post(`${environment.apiUrl}/events/`, eventData);
}
getEvent(eventId: string): Observable<any> {
return this.http.get(`${environment.apiUrl}/events/${eventId}`);
}
PS2:这是'onSubmit()'方法中使用的GeolocationService
方法:
geocodeAddress(address: string): Observable<google.maps.GeocoderResult[]> {
const response: Subject<google.maps.GeocoderResult[]>
= new Subject<google.maps.GeocoderResult[]>();
const request: google.maps.GeocoderRequest = { address };
this.geocoder.geocode(request,
(results: google.maps.GeocoderResult[]) => {
response.next(results);
}
);
return response;
}
更新
onSubmit() {
this.isSendingRequest = true;
this.geolocationService.geocodeAddress(this.location.value).subscribe(
(results: google.maps.GeocoderResult[]) => {
this.zone.run(() => π
if (results && results.length) {
const eventData: EventData = {
name: this.name.value,
location: [results[0].geometry.location.lat(), results[0].geometry.location.lng()],
startDate: this.datetimeService.convertDateAndTimeToISOString(this.startDate.value, this.startTime.value),
endingDate: this.datetimeService.convertDateAndTimeToISOString(this.endingDate.value, this.endingTime.value),
description: this.description.value,
sport: this.sport.value,
intensity: this.intensity.value,
fee: this.fee.value,
maxPlayers: this.maxPlayers.value
};
this.eventService.createEvent(eventData).subscribe(
(res: any) => {
this.alertService.createAlert({ message: EVENT_CREATED_MESSAGE, type: AlertType.Success });
this.router.navigate(['events', res.data.event.id]);
}
);
} else {
this.handleInvalidLocationError();
}
}
});
);
}
原创
也许事件是在 Angular 区域之外发出的。
尝试:
constructor(private zone: NgZone) { }
和:
this.zone.run(() => this.router.navigate(['events', res.data.event.id]));
如果这能解决问题,您应该修复 EventService
根据订阅发生的顺序,您可能会完全错过该活动。考虑使用 shareReplay(1)
并公开一个事件。
或者,将事件的订阅移至构造函数:
constructor(
private activatedRoute: ActivatedRoute,
private eventService: EventService
) {
this.getEvent();
}
ngOnInit() {
}