ngIf 的组件初始化不会触发 ngOnInit
Component initialization by ngIf does not trigger ngOnInit
我有一个 parent 组件,其中一些 child 是基于 ngIf 评估呈现的。
我在 Angular 8.1.3
parent 组件
import { ActivatedRoute } from '@angular/router';
import {FirstStageViewComponent} from "src/app/first-stage-view/first-stage-view.component";
import {SecondStageViewComponent} from "src/app/second-stage-view/second-stage-view.component";
import {SecondStageFormComponent} from "src/app/second-stage-form/second-stage-form.component";
import {ThirdStageFormComponent} from "src/app/third-stage-form/third-stage-form.component";
import {ThirdStageViewComponent} from "src/app/third-stage-view/third-stage-view.component";
import { ProdService } from "src/app/service/prod-service";
@Component({
selector: 'app-prod-view',
templateUrl: './prod-view.component.html',
styleUrls: ['./prod-view.component.css']
})
export class ProdViewComponent implements OnInit
{
id;
_stage: string;
constructor(private prodService: ProdService, private route: ActivatedRoute) { }
ngOnInit() {
this.route.params.subscribe(params => this.id=params.id);
this.prodService.get(this.id).subscribe((data: string) => (this._stage = data["_stage"]),
error => (console.log(error)));
}
talkBack(_updatedStage: string) {
this._stage=_updatedStage;
}
}
及其模板
<div class="container">
<div *ngIf="_stage>0">
<app-first-stage-view [id]=id></app-first-stage-view>
</div>
<div *ngIf="_stage==1 else stage2">
<app-second-stage-form [id]=id (talk)=talkBack($event)></app-second-stage-form>
</div>
<ng-template #stage2>
<div *ngIf="_stage>1">
<app-second-stage-view [id]=id></app-second-stage-view>
</div>
</ng-template>
<div *ngIf="_stage==2 else stage3">
<app-third-stage-form [id]=id (talk)=talkBack($event)></app-third-stage-form>
</div>
<ng-template #stage3>
<div *ngIf="_stage>2">
<app-third-stage-view [id]=id></app-third-stage-view>
</div>
</ng-template>
</div>
这是第二个 child 组件(未正确初始化的组件)
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { FormGroup, FormBuilder, FormArray, Validators } from "@angular/forms";
import { ThirdStageService } from "src/app/service/third-stage.service";
@Component( {
selector: 'app-third-stage-form',
templateUrl: './third-stage-form.component.html',
styleUrls: ['./third-stage-form.component.css']
} )
export class ThirdStageFormComponent implements OnInit {
tsForm: FormGroup;
@Input() id: string;
@Output() talk: EventEmitter<string> = new EventEmitter<string>();
constructor( private tsService: ThirdStageService,
private formBuilder: FormBuilder ) {}
ngOnInit() {
this.tsForm = this.formBuilder.group( {
ingredient: "TEST"
} );
}
}
以及用于测试的缩小模板
<div class="container">
<form [formGroup]="tsForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="name">{{ tsForm.controls[0].value }}</label> <input type="text"
class="form-control" id="ingredient" formControlName="ingredient"
required>
</div>
</form>
</div>
parent 从服务器检索 _stage 值,第一个 child 得到正确显示。
然后该组件通过 EventEmitter 将新的 _stage 值反馈给它的 parent,并且 parent 相应地更新其变量的值。
新值 (2) 是实际将我的第二个 ngIf 变为 true 的值,实际上第二个 child(称为 third-stage-form,不要混淆)构造函数被调用。但是它的 ngOnInit 没有启动。
默认值 "TEST" 没有显示在我的输入字段中,通过 Augury 检查组件树,我可以看到构造函数注入的两个依赖项存在,而在 ngOnInit 中创建的表单组不存在。
如果我创建一个直接指向我的 child 组件的新路由,一切都会按预期进行。
哈维尔,当你写作时
this.route.params.subscribe(params => this.id=params.id);
//here this.id has no value
this.prodService.get(this.id).subscribe(...)
你需要使用swithMap
this.route.params.pipe(
switchMap((params)=>{
//here you has "params"
this.id=params.id
//we want return
return this.prodService.get(this.id)
})
).subscribe((data: string) => (this._stage = data["_stage"]),
error => (console.log(error))
);
您正在使用异步的可观察对象。当请求完成时,subscribe()
中的任何内容都会被调用,这可能随时发生。
因此,您的 this.id
是在您已经对第二个可观察对象调用订阅之后设置的。您需要使用一些地图来确保订阅的顺序,例如 concatMap()
ngOnInit() {
this.route.params.pipe(
concatMap(params => this.prodService.get(params.id))
)
}
我有一个 parent 组件,其中一些 child 是基于 ngIf 评估呈现的。
我在 Angular 8.1.3
parent 组件
import { ActivatedRoute } from '@angular/router';
import {FirstStageViewComponent} from "src/app/first-stage-view/first-stage-view.component";
import {SecondStageViewComponent} from "src/app/second-stage-view/second-stage-view.component";
import {SecondStageFormComponent} from "src/app/second-stage-form/second-stage-form.component";
import {ThirdStageFormComponent} from "src/app/third-stage-form/third-stage-form.component";
import {ThirdStageViewComponent} from "src/app/third-stage-view/third-stage-view.component";
import { ProdService } from "src/app/service/prod-service";
@Component({
selector: 'app-prod-view',
templateUrl: './prod-view.component.html',
styleUrls: ['./prod-view.component.css']
})
export class ProdViewComponent implements OnInit
{
id;
_stage: string;
constructor(private prodService: ProdService, private route: ActivatedRoute) { }
ngOnInit() {
this.route.params.subscribe(params => this.id=params.id);
this.prodService.get(this.id).subscribe((data: string) => (this._stage = data["_stage"]),
error => (console.log(error)));
}
talkBack(_updatedStage: string) {
this._stage=_updatedStage;
}
}
及其模板
<div class="container">
<div *ngIf="_stage>0">
<app-first-stage-view [id]=id></app-first-stage-view>
</div>
<div *ngIf="_stage==1 else stage2">
<app-second-stage-form [id]=id (talk)=talkBack($event)></app-second-stage-form>
</div>
<ng-template #stage2>
<div *ngIf="_stage>1">
<app-second-stage-view [id]=id></app-second-stage-view>
</div>
</ng-template>
<div *ngIf="_stage==2 else stage3">
<app-third-stage-form [id]=id (talk)=talkBack($event)></app-third-stage-form>
</div>
<ng-template #stage3>
<div *ngIf="_stage>2">
<app-third-stage-view [id]=id></app-third-stage-view>
</div>
</ng-template>
</div>
这是第二个 child 组件(未正确初始化的组件)
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { FormGroup, FormBuilder, FormArray, Validators } from "@angular/forms";
import { ThirdStageService } from "src/app/service/third-stage.service";
@Component( {
selector: 'app-third-stage-form',
templateUrl: './third-stage-form.component.html',
styleUrls: ['./third-stage-form.component.css']
} )
export class ThirdStageFormComponent implements OnInit {
tsForm: FormGroup;
@Input() id: string;
@Output() talk: EventEmitter<string> = new EventEmitter<string>();
constructor( private tsService: ThirdStageService,
private formBuilder: FormBuilder ) {}
ngOnInit() {
this.tsForm = this.formBuilder.group( {
ingredient: "TEST"
} );
}
}
以及用于测试的缩小模板
<div class="container">
<form [formGroup]="tsForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="name">{{ tsForm.controls[0].value }}</label> <input type="text"
class="form-control" id="ingredient" formControlName="ingredient"
required>
</div>
</form>
</div>
parent 从服务器检索 _stage 值,第一个 child 得到正确显示。
然后该组件通过 EventEmitter 将新的 _stage 值反馈给它的 parent,并且 parent 相应地更新其变量的值。
新值 (2) 是实际将我的第二个 ngIf 变为 true 的值,实际上第二个 child(称为 third-stage-form,不要混淆)构造函数被调用。但是它的 ngOnInit 没有启动。
默认值 "TEST" 没有显示在我的输入字段中,通过 Augury 检查组件树,我可以看到构造函数注入的两个依赖项存在,而在 ngOnInit 中创建的表单组不存在。
如果我创建一个直接指向我的 child 组件的新路由,一切都会按预期进行。
哈维尔,当你写作时
this.route.params.subscribe(params => this.id=params.id);
//here this.id has no value
this.prodService.get(this.id).subscribe(...)
你需要使用swithMap
this.route.params.pipe(
switchMap((params)=>{
//here you has "params"
this.id=params.id
//we want return
return this.prodService.get(this.id)
})
).subscribe((data: string) => (this._stage = data["_stage"]),
error => (console.log(error))
);
您正在使用异步的可观察对象。当请求完成时,subscribe()
中的任何内容都会被调用,这可能随时发生。
因此,您的 this.id
是在您已经对第二个可观察对象调用订阅之后设置的。您需要使用一些地图来确保订阅的顺序,例如 concatMap()
ngOnInit() {
this.route.params.pipe(
concatMap(params => this.prodService.get(params.id))
)
}