在Router.navigate()上不触发角度变化检测

时间:2018-01-19 12:26:02

标签: angular angular2-changedetection

我在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中的任何位置之前,更改不会显示。但是当我直接通过网址导航到EventDetails组件时,页面才能正常呈现。

我在更改检测方面缺少什么?任何的想法?谢谢!

PS:EventService仅执行HTTP调用并将其作为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;
}

2 个答案:

答案 0 :(得分:1)

<强>更新

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

答案 1 :(得分:1)

根据订阅发生的顺序,您可能完全错过了该事件。考虑使用shareReplay(1)并公开事件。

或者,将事件的订阅移动到构造函数:

  constructor(
    private activatedRoute: ActivatedRoute,
    private eventService: EventService
  ) { 
     this.getEvent();
  }

  ngOnInit() {
  }