Angular: 访问在 "OnInit" 函数中声明的 this.id
Angular: Access this.id declared in an "OnInit" function
更新 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
函数提供给我的参数。我订阅了它们的参数并将它们记录在控制台中。到这里为止,一切正常。但我想从我的 OnInit
函数外部访问“this.id
”,因此我可以在 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);
});
}
}
这里的问题实际上归结为路由参数和可观察流的异步可用性。在为所有实际目的解决之前,您根本无法使用该值。您可以根据官方 Routing & Navigation 文档使用 switchMap
和 tap
等 RxJS 运算符,以确保路由参数 id
在使用前可用。 tap
可用于引入副作用,例如设置 class id
属性 from route params and/or setting title。您甚至可以创建 Observable<YourObject[]>
的 class 属性 并利用 Angular 异步管道来避免订阅和取消订阅以显示数据。
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 服务方法的 return:
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}`);
}
...
}
如果确实需要,您可以像现在一样为路由参数保存可观察对象,并根据需要在 class 的各个部分订阅id
将可供使用并可以显式设置您需要设置的内容。
我还会删除 @Injectable()
,因为没有理由在这里使用 @Component()
装饰器。
注意* 此示例中的异步管道运算符确保执行 Http 调用。否则需要 subscribe() (搜索 Angular http not executing 以查看类似问题)
希望对您有所帮助!
而不是
id: any;
您可以尝试使用 getter,像这样
public get id(): any {
this.route.params.subscribe(params => {
return params['id'];
}
}
在您的模板中,只需
{{ id }}
更新 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
函数提供给我的参数。我订阅了它们的参数并将它们记录在控制台中。到这里为止,一切正常。但我想从我的 OnInit
函数外部访问“this.id
”,因此我可以在 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);
});
}
}
这里的问题实际上归结为路由参数和可观察流的异步可用性。在为所有实际目的解决之前,您根本无法使用该值。您可以根据官方 Routing & Navigation 文档使用 switchMap
和 tap
等 RxJS 运算符,以确保路由参数 id
在使用前可用。 tap
可用于引入副作用,例如设置 class id
属性 from route params and/or setting title。您甚至可以创建 Observable<YourObject[]>
的 class 属性 并利用 Angular 异步管道来避免订阅和取消订阅以显示数据。
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 服务方法的 return:
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}`);
}
...
}
如果确实需要,您可以像现在一样为路由参数保存可观察对象,并根据需要在 class 的各个部分订阅id
将可供使用并可以显式设置您需要设置的内容。
我还会删除 @Injectable()
,因为没有理由在这里使用 @Component()
装饰器。
注意* 此示例中的异步管道运算符确保执行 Http 调用。否则需要 subscribe() (搜索 Angular http not executing 以查看类似问题)
希望对您有所帮助!
而不是
id: any;
您可以尝试使用 getter,像这样
public get id(): any {
this.route.params.subscribe(params => {
return params['id'];
}
}
在您的模板中,只需
{{ id }}