加载数据后设置反应形式(异步)- Angular 5
Set reactive form after data loaded (async) - Angular 5
我试图在从 API 加载值后更新表单值。我尝试使用 *ngIf
技术,但即使设置了表单,表单也不可见。
我无法分享完整的项目,但这里是组件模板和控制器
模板
<div class="page-title">
<h3> Edit news </h3>
</div>
<div class="partner-add-form">
<ng-container *ngIf='newsForm'>
<form action="" [formGroup]='newsForm' (ngSubmit)="onSubmit()">
<div class="row ">
<div class="input-field col s12 tooltip">
<input formControlName='title' [id]="'title'" [type]="'text'">
<label [for]="'title'">Title</label>
<validator-errors [control]='newsForm.get("title")'></validator-errors>
</div>
<div class="input-field col s12 tooltip">
<textarea class="materialize-textarea" formControlName='content' [id]="'content'"></textarea>
<label [for]="'content'">Content</label>
<validator-errors [control]='newsForm.get("content")'></validator-errors>
</div>
<div class="input-field col s12 margin-reset">
<mat-form-field class="full-width">
<mat-select [formControl]='newsForm.controls["partner_id"]'>
<mat-option disabled selected>Categories</mat-option>
<mat-option *ngFor="let partner of partners.data" [value]="partner.id">
{{ partner.name }} </mat-option>
</mat-select>
</mat-form-field>
<validator-errors [control]='newsForm.controls["partner_id"]'></validator-errors>
</div>
<div class="file-field col s12 input-field">
<div class="btn">
<span>File</span>
<input (change)="fileChangeListener($event)" type="file"> </div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" placeholder="Upload one or more files"> </div>
</div>
<div class="col s12">
<div class="flex flex-middle flex-center crop-area">
<img-cropper #cropper [image]="data" [settings]="cropperSettings"></img-cropper>
<i class="material-icons">arrow_forward</i>
<div class="result rounded z-depth-1">
<img [src]="data.image " *ngIf="data.image " [width]="cropperSettings.croppedWidth"
[height]="cropperSettings.croppedHeight"> </div>
</div>
</div>
<div class="col s12 form-bottom">
<div class="left">
<button type="button" onclick='window.history.back()' class='btn btn-large waves-effect waves-light '>
<i class="material-icons">keyboard_arrow_left</i>
<span>Back</span>
</button>
</div>
<div class="right">
<button [ngClass]="{'disabled':(newsForm['invalid']) || isSubmitting || !data.image }" type="submit" class='btn btn-large waves-effect waves-light '>
Submit </button>
</div>
</div>
</div>
</form>
</ng-container>
</div>
控制器
partners;
news = {};
newsForm: FormGroup;
ngOnInit() {
setTimeout(() => {
this._dashboardService.routeChangeStarted();
}, 0);
this._activatedRoute.params.subscribe(params => {
this.news["id"] = params["id"];
this.getPartners().then(data => {
this.getNews().then(data=>{
this.setForm();
})
});
});
}
setForm() {
this.newsForm = this._formBuilder.group({
title: [this.news['title'], [Validators.required]],
content: [this.news['content'], [Validators.required]],
partner_id: [this.news['partner']['id'], [Validators.required]]
});
console.log(new Boolean(this.newsForm));
}
getPartners() {
return Promise((res, rej) => {
setTimeout(() => {
this._dashboardService.progressStarted();
this._dashboardService.routeChangeStarted();
}, 0);
this._partnerService.getPartners().subscribe(
partners => {
if (partners.status == 200) {
this.partners = partners;
res(partners.data);
} else {
this._errorActions.errorHandler(partners.status);
}
setTimeout(() => {
this._dashboardService.progressFinished();
this._dashboardService.routeChangeFinished();
}, 0);
},
error => {
this._notificationService.warning("Ups, something went wrong");
}
);
});
}
getNews() {
setTimeout(() => {
this._dashboardService.routeChangeStarted();
this._dashboardService.progressStarted();
}, 0);
return Promise((res, rej) => {
this._newsService.getNews(this.news["id"]).subscribe(
data => {
if (data["status"] == 200) {
Object.assign(this.news, data["data"]);
res(this.news);
} else {
this._errorActions.errorHandler(data["status"]);
}
setTimeout(() => {
this._dashboardService.progressFinished();
this._dashboardService.routeChangeFinished();
}, 0);
},
error => {
this._notificationService.error("Ups, something went wrong");
}
);
});
}
有什么问题?设置表单后,它甚至不显示表单本身。从 API?
加载数据后是否有另一种设置表单值的方法
我遇到过这个问题,我不知道我的解决方案是否最好,但它有效。该技术是使用一个 loaded: boolean
启动到 false
并且一旦你的数据完全接收到你的组件中你将它设置为 true
这里有一个例子:
.html:
<div *ngIf="loaded == false">
<h2>loading ...</h2>
</div>
<div *ngIf="loaded == true">
// your template goes here
</div>
并在您的 .ts 中:
loaded: boolean = false;
// your code ....
ngOnInit() {
setTimeout(() => {
this._dashboardService.routeChangeStarted();
}, 0);
this._activatedRoute.params.subscribe(params => {
this.news["id"] = params["id"];
this.getPartners().then(data => {
this.getNews().then(data=>{
this.setForm();
// here is the important part!
this.loaded = true
})
});
});
}
您可以创建一个单独的函数来用数据填充表单。您可以在从 API.
获取数据后调用此函数
变体 1:setValue
官方 angular 文档:setValue
With setValue, you assign every form control value at once by passing in a data object whose properties exactly match the form model behind the FormGroup.
示例:
updateValues(dataObject: any) {
this.heroForm.setValue({
name: this.hero.name,
address: this.hero.addresses[0] || new Address()
});
}
变体 2:patchValue
官方 angular 文档:patchValue
With patchValue, you can assign values to specific controls in a FormGroup by supplying an object of key/value pairs for just the controls of interest.
示例:
updateValues(dataObject: any) {
this.heroForm.patchValue({
name: this.hero.name
});
}
您可以使用 setValue
或 patchValue
数据异步 FormGroup
。
private initForm(): void {
// For update product
if (this.isUpdate) {
this.productService.getProduct(this.id)
.subscribe((product: Product) => {
this.productForm.patchValue({
name: product.name,
price: product.price,
description: product.description,
image: product.image
});
});
}
// For create product
this.productForm = new FormGroup({
name: new FormControl(null, [
Validators.required,
Validators.minLength(8),
Validators.maxLength(35)
]),
price: new FormControl(null, [
Validators.required,
Validators.min(5000),
Validators.max(50000000),
]),
description: new FormControl(null, [
Validators.required,
Validators.minLength(8),
Validators.maxLength(500)
]),
image: new FormControl(null, Validators.required)
});
}
为了通过 promise 订阅更新表单,我需要手动 运行 更改检测。这可以通过导入
来实现
constructor(private changeDetectorRef: ChangeDetectorRef) {
}
和运行宁
this.changeDetectorRef.detectChanges();
我试图在从 API 加载值后更新表单值。我尝试使用 *ngIf
技术,但即使设置了表单,表单也不可见。
我无法分享完整的项目,但这里是组件模板和控制器
模板
<div class="page-title">
<h3> Edit news </h3>
</div>
<div class="partner-add-form">
<ng-container *ngIf='newsForm'>
<form action="" [formGroup]='newsForm' (ngSubmit)="onSubmit()">
<div class="row ">
<div class="input-field col s12 tooltip">
<input formControlName='title' [id]="'title'" [type]="'text'">
<label [for]="'title'">Title</label>
<validator-errors [control]='newsForm.get("title")'></validator-errors>
</div>
<div class="input-field col s12 tooltip">
<textarea class="materialize-textarea" formControlName='content' [id]="'content'"></textarea>
<label [for]="'content'">Content</label>
<validator-errors [control]='newsForm.get("content")'></validator-errors>
</div>
<div class="input-field col s12 margin-reset">
<mat-form-field class="full-width">
<mat-select [formControl]='newsForm.controls["partner_id"]'>
<mat-option disabled selected>Categories</mat-option>
<mat-option *ngFor="let partner of partners.data" [value]="partner.id">
{{ partner.name }} </mat-option>
</mat-select>
</mat-form-field>
<validator-errors [control]='newsForm.controls["partner_id"]'></validator-errors>
</div>
<div class="file-field col s12 input-field">
<div class="btn">
<span>File</span>
<input (change)="fileChangeListener($event)" type="file"> </div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" placeholder="Upload one or more files"> </div>
</div>
<div class="col s12">
<div class="flex flex-middle flex-center crop-area">
<img-cropper #cropper [image]="data" [settings]="cropperSettings"></img-cropper>
<i class="material-icons">arrow_forward</i>
<div class="result rounded z-depth-1">
<img [src]="data.image " *ngIf="data.image " [width]="cropperSettings.croppedWidth"
[height]="cropperSettings.croppedHeight"> </div>
</div>
</div>
<div class="col s12 form-bottom">
<div class="left">
<button type="button" onclick='window.history.back()' class='btn btn-large waves-effect waves-light '>
<i class="material-icons">keyboard_arrow_left</i>
<span>Back</span>
</button>
</div>
<div class="right">
<button [ngClass]="{'disabled':(newsForm['invalid']) || isSubmitting || !data.image }" type="submit" class='btn btn-large waves-effect waves-light '>
Submit </button>
</div>
</div>
</div>
</form>
</ng-container>
</div>
控制器
partners;
news = {};
newsForm: FormGroup;
ngOnInit() {
setTimeout(() => {
this._dashboardService.routeChangeStarted();
}, 0);
this._activatedRoute.params.subscribe(params => {
this.news["id"] = params["id"];
this.getPartners().then(data => {
this.getNews().then(data=>{
this.setForm();
})
});
});
}
setForm() {
this.newsForm = this._formBuilder.group({
title: [this.news['title'], [Validators.required]],
content: [this.news['content'], [Validators.required]],
partner_id: [this.news['partner']['id'], [Validators.required]]
});
console.log(new Boolean(this.newsForm));
}
getPartners() {
return Promise((res, rej) => {
setTimeout(() => {
this._dashboardService.progressStarted();
this._dashboardService.routeChangeStarted();
}, 0);
this._partnerService.getPartners().subscribe(
partners => {
if (partners.status == 200) {
this.partners = partners;
res(partners.data);
} else {
this._errorActions.errorHandler(partners.status);
}
setTimeout(() => {
this._dashboardService.progressFinished();
this._dashboardService.routeChangeFinished();
}, 0);
},
error => {
this._notificationService.warning("Ups, something went wrong");
}
);
});
}
getNews() {
setTimeout(() => {
this._dashboardService.routeChangeStarted();
this._dashboardService.progressStarted();
}, 0);
return Promise((res, rej) => {
this._newsService.getNews(this.news["id"]).subscribe(
data => {
if (data["status"] == 200) {
Object.assign(this.news, data["data"]);
res(this.news);
} else {
this._errorActions.errorHandler(data["status"]);
}
setTimeout(() => {
this._dashboardService.progressFinished();
this._dashboardService.routeChangeFinished();
}, 0);
},
error => {
this._notificationService.error("Ups, something went wrong");
}
);
});
}
有什么问题?设置表单后,它甚至不显示表单本身。从 API?
加载数据后是否有另一种设置表单值的方法我遇到过这个问题,我不知道我的解决方案是否最好,但它有效。该技术是使用一个 loaded: boolean
启动到 false
并且一旦你的数据完全接收到你的组件中你将它设置为 true
这里有一个例子:
.html:
<div *ngIf="loaded == false">
<h2>loading ...</h2>
</div>
<div *ngIf="loaded == true">
// your template goes here
</div>
并在您的 .ts 中:
loaded: boolean = false;
// your code ....
ngOnInit() {
setTimeout(() => {
this._dashboardService.routeChangeStarted();
}, 0);
this._activatedRoute.params.subscribe(params => {
this.news["id"] = params["id"];
this.getPartners().then(data => {
this.getNews().then(data=>{
this.setForm();
// here is the important part!
this.loaded = true
})
});
});
}
您可以创建一个单独的函数来用数据填充表单。您可以在从 API.
获取数据后调用此函数变体 1:setValue
官方 angular 文档:setValue
With setValue, you assign every form control value at once by passing in a data object whose properties exactly match the form model behind the FormGroup.
示例:
updateValues(dataObject: any) {
this.heroForm.setValue({
name: this.hero.name,
address: this.hero.addresses[0] || new Address()
});
}
变体 2:patchValue
官方 angular 文档:patchValue
With patchValue, you can assign values to specific controls in a FormGroup by supplying an object of key/value pairs for just the controls of interest.
示例:
updateValues(dataObject: any) {
this.heroForm.patchValue({
name: this.hero.name
});
}
您可以使用 setValue
或 patchValue
数据异步 FormGroup
。
private initForm(): void {
// For update product
if (this.isUpdate) {
this.productService.getProduct(this.id)
.subscribe((product: Product) => {
this.productForm.patchValue({
name: product.name,
price: product.price,
description: product.description,
image: product.image
});
});
}
// For create product
this.productForm = new FormGroup({
name: new FormControl(null, [
Validators.required,
Validators.minLength(8),
Validators.maxLength(35)
]),
price: new FormControl(null, [
Validators.required,
Validators.min(5000),
Validators.max(50000000),
]),
description: new FormControl(null, [
Validators.required,
Validators.minLength(8),
Validators.maxLength(500)
]),
image: new FormControl(null, Validators.required)
});
}
为了通过 promise 订阅更新表单,我需要手动 运行 更改检测。这可以通过导入
来实现constructor(private changeDetectorRef: ChangeDetectorRef) {
}
和运行宁
this.changeDetectorRef.detectChanges();