J'essaie de mettre à jour les valeurs du formulaire après avoir chargé des valeurs à partir d'une API. J'ai essayé d'utiliser le *ngIf
technique mais le formulaire n'est pas visible même lorsque le formulaire est défini.
Je ne suis pas en mesure de partager le projet complet, mais voici le modèle de composant et le contrôleur
modèle
<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>
Contrôleur
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");
}
);
});
}
Quel est le problème? Il n'affiche même pas le formulaire lui-même après avoir défini le formulaire. Existe-t-il une autre façon de définir les valeurs du formulaire après le chargement des données à partir d'une API?
Vous pouvez créer une fonction distincte pour remplir votre formulaire avec des données. Vous pouvez appeler cette fonction après avoir obtenu des données d'une API.
Variante 1: setValue
Documentation officielle angular: setValue
Avec setValue, vous affectez chaque valeur de contrôle de formulaire à la fois en passant un objet de données dont les propriétés correspondent exactement au modèle de formulaire derrière le FormGroup.
Exemple:
updateValues(dataObject: any) {
this.heroForm.setValue({
name: this.hero.name,
address: this.hero.addresses[0] || new Address()
});
}
Variante 2: patchValue
Documentation officielle angular: patchValue
Avec patchValue, vous pouvez affecter des valeurs à des contrôles spécifiques dans un FormGroup en fournissant un objet de paires clé/valeur uniquement pour les contrôles d'intérêt.
Exemple:
updateValues(dataObject: any) {
this.heroForm.patchValue({
name: this.hero.name
});
}
j'ai été confronté à ce problème, je ne sais pas si ma solution est la meilleure, mais ça marche. La technique consiste à utiliser un loaded: boolean
que vous initiez à false
et une fois que vos données sont entièrement reçues dans votre composant, vous les définissez sur true
en voici un exemple:
.html:
<div *ngIf="loaded == false">
<h2>loading ...</h2>
</div>
<div *ngIf="loaded == true">
// your template goes here
</div>
et dans vos .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
})
});
});
}
Vous pouvez utiliser setValue
ou patchValue
quelles données sont asynchrones pour vous 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)
});
}