正如您在下面的附图中看到的,我在Angular 7中构建了一个表单 . 表单包含多个级别的嵌套字段组 . 按“添加轨道”按钮时,外部字段组被推送到dom . 然后在里面你可以按“”在每个外部字段组中添加字段 .
Problem 1: 我继续收到以下错误,"Add Track"只将完整的字段组推送到索引1,传递它缺少"+"按钮的字段,这些按钮由HTML中的嵌套* ngFor循环填充 .
Error:
ERROR Error: Cannot find control with path: 'albumTracks -> 1 -> audioSources -> 1'
at _throwError (forms.js:1775)
at setUpFormContainer (forms.js:1757)
at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective.addFormGroup (forms.js:4541)
at FormGroupName.push../node_modules/@angular/forms/fesm5/forms.js.AbstractFormGroupDirective.ngOnInit (forms.js:1887)
at checkAndUpdateDirectiveInline (core.js:9243)
at checkAndUpdateNodeInline (core.js:10507)
at checkAndUpdateNode (core.js:10469)
at debugCheckAndUpdateNode (core.js:11102)
at debugCheckDirectivesFn (core.js:11062)
at Object.eval [as updateDirectives] (AddAlbumsDinamicComponent.html:103)
Problem 2: 当我填写表单并单击"Save"按钮然后执行onSubmit()方法并通过以下方式获取所有输入的表单值:"this.albumForm.value"时,我丢失了一些我输入到字段中的值,这些值是通过按"Add Track"和"+"按钮动态推送的 .
试图在网上找到答案,但找不到任何类似于我想做的事情 . 所有在线示例均适用于简单表单,而不适用于多级嵌套表单组 . 也是Angular的新手,需要帮助 . S.O.S,非常感谢你的帮助 .
component.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray } from '@angular/forms';
import { PostRequestService } from '../post-request.service';
@Component({
selector: 'app-add-albums-dinamic',
templateUrl: './add-albums-dinamic.component.html',
styleUrls: ['./add-albums-dinamic.component.css']
})
export class AddAlbumsDinamicComponent implements OnInit {
albumForm: FormGroup;
items: FormArray;
arrayElement: FormArray;
submitted = false;
constructor(private formBuilder: FormBuilder, private postRequestService: PostRequestService) {}
ngOnInit() {
this.albumForm = this.formBuilder.group({
albumTitle: '',
albumCoverImage: '',
datePublished: '',
albumPurchaseSources: this.formBuilder.array([ this.createAlbumPurchaseSource() ]),
albumTracks: this.formBuilder.array([ this.albumTracksDetails() ])
});
}
createAlbumPurchaseSource(): FormGroup {
return this.formBuilder.group({
albumPurchaseSourceName: '',
albumPurchaseURL: ''
});
}
createAudioSource(): FormGroup {
return this.formBuilder.group({
audioSourceName: '',
audioSourceURL: ''
});
}
createVideoSource(): FormGroup {
return this.formBuilder.group({
videoSourceName: '',
videoSourceURL: ''
});
}
createTrackPurchaseSource(): FormGroup {
return this.formBuilder.group({
trackPurchaseSourceName: '',
trackPurchaseSourceURL: ''
});
}
albumTracksDetails(): FormGroup {
return this.formBuilder.group({
trackTitle: '',
trackGenre: '',
audioSources: this.formBuilder.array([ this.createAudioSource() ]),
videoSources: this.formBuilder.array([ this.createVideoSource() ]),
trackPurchaseSources: this.formBuilder.array([ this.createTrackPurchaseSource() ]),
downloadURL: ''
});
}
addAudioSource(i: number): void {
const control = (<FormArray>this.albumForm.controls['albumTracks']).at(i).get('audioSources') as FormArray;
control.push(this.createAudioSource());
}
addVideoSource(i: number): void {
const control = (<FormArray>this.albumForm.controls['albumTracks']).at(i).get('videoSources') as FormArray;
control.push(this.createVideoSource());
}
addTrackPurchaseSource(i: number): void {
const control = (<FormArray>this.albumForm.controls['albumTracks']).at(i).get('trackPurchaseSources') as FormArray;
control.push(this.createTrackPurchaseSource());
}
addTracks(): void {
this.items = this.albumForm.get('albumTracks') as FormArray;
this.items.push(this.albumTracksDetails());
}
addAlbumPurchaseSources(): void {
this.items = this.albumForm.get('albumPurchaseSources') as FormArray;
this.items.push(this.createAlbumPurchaseSource());
}
onSubmit() {
this.submitted = true;
this.postRequestService.
postRequest(this.albumForm.value)
.subscribe(
(val) => {
console.log("POST call successful value returned in body",
val);
},
response => {
console.log("POST call in error", response);
},
() => {
console.log("The POST observable is now completed.");
});
}
}
component.html
<div class="container">
<div id="outer-container">
<div id="sidebar">
<div class="mycontent-left">
<app-artist-admin-sidebar></app-artist-admin-sidebar>
</div>
</div>
<div id="content">
<form [formGroup]="albumForm" (ngSubmit)="onSubmit()" novalidate>
<div><font size="4">Album Details:</font></div>
<div class="row">
<div class="col">
<div class="col-sm-2 control-label"><font size="3">Album Title:</font></div>
<div class="col-sm-3 nopadding">
<input type="text" class="form-control" id="album_title" name="album_title" formControlName="albumTitle"
placeholder="Album Title">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="col-sm-3 control-label"><font size="3">Album Cover Image:</font></div>
<div class="col-sm-3 nopadding">
<input type="file" class="form-control" id="cover_image" name="cover_image"
formControlName="albumCoverImage" placeholder="Album Cover Image">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="col-sm-3 control-label"><font size="3">Date Published:</font></div>
<div class="col-sm-3 nopadding">
<input type="date" class="form-control" id="date_published" name="date_published"
formControlName="datePublished" placeholder="Date Published">
</div>
</div>
</div>
<div formArrayName="albumPurchaseSources"
*ngFor="let item of albumForm.get('albumPurchaseSources').controls; let i = index;">
<div [formGroupName]="i">
<div class="row">
<div class="col">
<div class="col-sm-2 control-label"><font size="3">Album Purchase Source:</font></div>
<div class="col-sm-3 nopadding">
<input type="text" class="form-control" id="album_purchase_source_name"
name="album_purchase_source_name" formControlName="albumPurchaseSourceName"
placeholder="Source Name">
</div>
<div class="col-sm-3 nopadding">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" id="album_purchase_url" name="album_purchase_url"
formControlName="albumPurchaseURL" placeholder="URL">
<div class="input-group-btn">
<button class="btn btn-success" type="button" (click)="addAlbumPurchaseSources();"><span
class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<hr/>
<div><font size="4">Album Tracks Details:</font></div>
<div formArrayName="albumTracks" *ngFor="let item of albumForm.get('albumTracks').controls; let i = index;">
<div [formGroupName]="i">
<div class="row">
<div class="col">
<div class="col-sm-2 control-label"><font size="3">Track Title:</font></div>
<div class="col-sm-3 nopadding">
<input type="text" class="form-control" id="track_title" name="track_title"
formControlName="trackTitle" placeholder="Track Title">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="col-sm-2 control-label"><font size="3">Track Genre:</font></div>
<div class="col-sm-3 nopadding">
<input type="text" class="form-control" id="genre" name="genre" formControlName="trackGenre"
placeholder="Genre">
</div>
</div>
</div>
<div formArrayName="audioSources" *ngFor="let audioItem of item.controls['audioSources'].controls; let audioi=index;">
<div [formGroupName]="i">
<div class="row">
<div class="col">
<div class="col-sm-2 control-label"><font size="3">Audio:</font></div>
<div class="col-sm-3 nopadding">
<input type="text" class="form-control" id="audio_source_name" name="audio_source_name" formControlName="audioSourceName" placeholder="Audio Source Name">
</div>
<div class="col-sm-3 nopadding">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" id="audio_url" name="audio_url" formControlName="audioSourceURL" placeholder="Audio Source URL">
<div class="input-group-btn">
<button class="btn btn-success" type="button" (click)="addAudioSource(i);"><span
class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div formArrayName="videoSources" *ngFor="let videoItem of item.controls['videoSources'].controls; let videoi = index;">
<div [formGroupName]="i">
<div class="row">
<div class="col">
<div class="col-sm-2 control-label"><font size="3">Video:</font></div>
<div class="col-sm-3 nopadding">
<input type="text" class="form-control" id="video_source_name" name="video_source_name" formControlName="videoSourceName" placeholder="Video Source Name">
</div>
<div class="col-sm-3 nopadding">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" id="video_url" name="video_url" formControlName="videoSourceURL" placeholder="Video Source URL">
<div class="input-group-btn">
<button class="btn btn-success" type="button" (click)="addVideoSource(i);"><span
class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div formArrayName="trackPurchaseSources" *ngFor="let trackPurchaseItem of item.controls['trackPurchaseSources'].controls; let purchasei = index;">
<div [formGroupName]="i">
<div class="row">
<div class="col">
<div class="col-sm-2 control-label"><font size="3">Track Purchase Source:</font></div>
<div class="col-sm-3 nopadding">
<input type="text" class="form-control" id="purchase_source_name" name="purchase_source_name" formControlName="trackPurchaseSourceName" placeholder="Purchase Source Name">
</div>
<div class="col-sm-3 nopadding">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" id="purchase_url" name="purchase_url" formControlName="trackPurchaseSourceURL" placeholder="Purchase Source URL">
<div class="input-group-btn">
<button class="btn btn-success" type="button" (click)="addTrackPurchaseSource(i);"><span
class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="col-sm-2 control-label"><font size="3">Download:</font></div>
<div class="col-sm-3 nopadding">
<input type="text" class="form-control" id="download_url" name="download_url"
formControlName="downloadURL" placeholder="Download URL">
</div>
</div>
</div>
<hr>
</div>
</div>
<div class="form-group">
<button class="btn btn-success" type="button" (click)="addTracks();">Add Track</button>
</div>
<div class="form-group">
<button class="btn btn-primary">Save</button>
</div>
</form>
</div>
</div>
</div>
1 回答
在这里工作:https://stackblitz.com/edit/so-53246132
Problem #1:
但应该是:
videoi
和purchasei
也是如此 .Problem #2:
也可能会有变化: