角度:访问在“ OnInit”函数中声明的this.id

时间:2018-08-25 18:49:56

标签: javascript angular class parameters angular-ui-router

更新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调用中,该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 :(得分:0)

这里的问题实际上归结为路由参数和可观察流的异步可用性。您不能使用该值,直到将其解析为所有实际用途为止。您可以根据官方Routing & Navigation文档使用RxJS运算符,例如switchMaptap,以确保在使用前可以使用路由参数idtap可用于引入副作用,例如从路由参数和/或设置标题中设置类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调用。否则,需要一个subscription()(在SO中搜索Angular http不会执行以查看类似问题)

希望有帮助!

答案 1 :(得分:0)

代替

id: any;

您可以尝试使用吸气剂,例如

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

在模板中,

{{ id }}