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() {
  }