Angular: доступ к this.id, объявленному в функции «OnInit» - PullRequest
0 голосов
/ 25 августа 2018

Обновление 1

После того, как я прочитал предложения Alexanders, я обновил код и не получил ошибку обратно. Но Angular больше не делает запрос к серверу, что делает меня любопытным. А также pageTitle не обновляется.

appointmentDetail.component.html

{{appointmentDetail.time}}

appointmentDetail.component.ts

import { Component, OnInit, OnDestroy, Injectable } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { APIService } from './../../../api.service';
import { Observable } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';

@Component({
  selector: 'app-appointmentdetail',
  templateUrl: './appointmentDetail.component.html',
  styleUrls: ['./appointmentDetail.component.scss']
})
export class AppointmentDetailComponent implements OnInit {
  id: any;
  appointmentDetail$: Observable<Object>; // I'd really create an interface for appointment or whatever instead of  object or any
  pageTitle = 'Some Default Title Maybe';

  constructor(
    private route: ActivatedRoute,
    private title: Title,
    private apiService: APIService
  ) {}

  ngOnInit() {
    this.appointmentDetail$ = this.route.paramMap.pipe(
      tap((params: ParamMap) => {
        this.id = params.get('id');
        // Or this.id = +params.get('id'); to coerce to number maybe
        this.pageTitle = 'Termin' + this.id;
        this.title.setTitle(this.pageTitle);
      }),
      switchMap(() => this.apiService.getAppointmentDetailsById(this.id))
    );
  }
  public getData() {
    this.apiService
      .getAppointmentDetailsById(this.id)
      .subscribe((data: Observable<Object>) => {
        this.appointmentDetail$ = data;
        console.log(data);
      });
  }
}

api.service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class APIService {
  API_URL = 'http://localhost:5000';
  constructor(private httpClient: HttpClient) {}
  getAppointments() {
    return this.httpClient.get(`${this.API_URL}/appointments/`);
  }
  getAppointmentDetailsById(id) {
    return this.httpClient.get(`${this.API_URL}/appointments/${id}`);
  }
  getAppointmentsByUser(email) {
    return this.httpClient.get(`${this.API_URL}/user/${email}/appointments`);
  }
  getCertificatesByUser(email) {
    return this.httpClient.get(`${this.API_URL}/user/${email}/certificates`);
  }
}

Как видите, я хочу получить этот параметр id из параметров маршрутизатора и передать его в мой вызов API, который будет выполнять Angular HTTP-запрос. Надеюсь, я прав, хаха.


Оригинальный вопрос

В настоящее время я столкнулся с неприятной проблемой. Дело в том, что я хочу прочитать параметры, которые мне дают ActivatedRouter и функция Angular OnInit. Я подписываю их параметры и регистрирую их в консоли. Пока здесь все работает нормально. Но я хочу получить доступ к «this.id» снаружи от моей OnInit функции, поэтому я могу использовать его, например, на pageTitle.

Но this.id не определен. Таким образом, заголовок страницы - Termineundefined.

Исходный код:

import { Component, OnInit, OnDestroy, Injectable } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { APIService } from './../../api.service';

@Component({
  selector: 'app-appointment-details',
  templateUrl: './appointment-details.component.html',
  styleUrls: ['./appointment-details.component.scss']
})
@Injectable()
export class AppointmentDetailsComponent implements OnInit, OnDestroy {
  private routeSub: any;
  id: any;
  private appointmentDetail: Array<object> = [];
  constructor(
    private route: ActivatedRoute,
    private title: Title,
    private apiService: APIService
  ) {}

  pageTitle = 'Termin' + this.id;

  ngOnInit() {
    this.title.setTitle(this.pageTitle);
    this.getData();

    this.routeSub = this.route.params.subscribe(params => {
      console.log(params);
      this.id = params['id'];
    });
  }

  ngOnDestroy() {
    this.routeSub.unsubscribe();
  }

  public getData() {
    this.apiService
      .getAppointmentDetailsById(this.id)
      .subscribe((data: Array<object>) => {
        this.appointmentDetail = data;
        console.log(data);
      });
  }
}

Ответы [ 2 ]

0 голосов
/ 25 августа 2018

Вместо

id: any;

Вы можете попробовать использовать геттер, например:

public get id(): any {
  this.route.params.subscribe(params => {
    return params['id'];
   }
}

В вашем шаблоне просто

{{ id }}
0 голосов
/ 25 августа 2018

Проблема здесь действительно сводится к асинхронной доступности параметров маршрута и наблюдаемых потоков.Вы просто не можете использовать значение, пока оно не разрешено для всех практических целей.Вы можете использовать операторы RxJS, такие как switchMap и tap в соответствии с официальной документацией Маршрутизация и навигация , чтобы обеспечить доступ к параметру маршрута id перед использованием.tap может использоваться для введения побочных эффектов, таких как установка свойства класса id из параметров маршрута и / или настройка заголовка.Вы даже можете создать свойство класса для Observable<YourObject[]> и использовать Angular Async Pipe, чтобы избежать подписки и отписки для отображения данных.

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { APIService, MyFancyInterface } from './../../api.service';
import { Observable } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';

@Component({
  selector: 'app-appointment-details',
  templateUrl: './appointment-details.component.html',
  styleUrls: ['./appointment-details.component.scss']
})
export class AppointmentDetailsComponent implements OnInit {
  id: any;
  appointmentDetail$: Observable<MyFancyInterface>;
  appointmentDetail: MyFancyInterface;
  pageTitle = 'Some Default Title Maybe';

  constructor(
    private route: ActivatedRoute,
    private title: Title,
    private apiService: APIService
  ) {}

  ngOnInit() {
    this.appointmentDetail$ = this.route.paramMap.pipe(
      tap((params: ParamMap) => {
        this.id = params.get('id')
        // Or this.id = +params.get('id'); to coerce to type number maybe
        this.pageTitle = 'Termin' + this.id;
        this.title.setTitle(this.pageTitle);
      }),
      switchMap(() => this.apiService.getAppointmentDetailsById(this.id))
    );

    /* Or
    this.route.paramMap.pipe(
      tap((params: ParamMap) => {
        this.id = params.get('id')
        // Or this.id = +params.get('id'); to coerce to type number maybe
        this.pageTitle = 'Termin' + this.id;
        this.title.setTitle(this.pageTitle);
      }),
      switchMap(() => this.apiService.getAppointmentDetailsById(this.id))
    ).subscribe((data: MyFancyInterface) => {
      this.appointmentDetail = data;
    });
    */
  }

}

Шаблон:

<div>{{(appointmentDetail | async)?.id}}</div>

Я быРекомендую создать интерфейс для представления вашей модели данных и напечатать возвращаемый вами метод службы API:

import { Observable } from 'rxjs';

// maybe put this into another file
export interface MyFancyInterface {
  id: number;
  someProperty: string;
  ...
}

export class APIService {
  ...
  getAppointmentDetailsById(id): Observable<MyFancyInterface> {
    return this.httpClient.get<MyFancyInterface>(`${this.API_URL}/appointments/${id}`);
  }
  ...
}

Если вам действительно нужно, вы можете сохранить наблюдаемое, как сейчас, для параметров маршрута и подписаться кактребуется в различных частях класса, но таким продемонстрированным способом вы почти точно знаете, что параметр маршрута id будет доступен для использования и может явно задавать то, что вам нужно установить.

Я бы также удалил@Injectable(), поскольку нет причины иметь его здесь с декоратором @Component().

Примечание * оператор асинхронного канала в этом примере обеспечивает выполнение вызова Http.В противном случае требуется подписка () (для поиска похожих проблем ищите Angular http, который не выполняется)

Надеюсь, это поможет!

...