I have an assignment to create and edit volumes with angular. I am using reactive form but i cannot take volumes authors when i try to edit them. I am dynamically generating them when i am creating volume but i cannot see them on 'Edit'. I tried many ways and i was seeing all kind of errors on the browser console. Here is the code:
public createMyVolumeForm: FormGroup;
constructor(private fb: FormBuilder,
private router: Router,
private volumeService: VolumeService,
private route: ActivatedRoute) {
this.createMyVolumeForm = this.fb.group({
id: ['', [Validators.required]],
volumeInfo: this.fb.group({
title: ['', [Validators.required]],
authors: this.fb.array([
this.fb.control('')
]),
publisher: ['', [Validators.required]],
publishedDate: ['', [Validators.required]],
pageCount: ['', [Validators.required]],
imageLinks: this.fb.group({
thumbnail: ['', [Validators.required]]
})
})
});
}
createMyVolume(): void {
this.volumeService.createMyVolume(this.createMyVolumeForm.value)
.subscribe(data => {
this.router.navigateByUrl('my-volumes');
console.log(this.createMyVolumeForm.value);
});
}
ngOnInit(): void {
this.route.paramMap.subscribe(params => {
const volumeId = params.get('id');
if (volumeId) {
this.getCurrentVolume(volumeId);
}
});
}
private getCurrentVolume(id: string): void {
this.volumeService.getVolume(id).pipe(take(1)).subscribe(
(volume: IVolume) => this.editVolume(volume)
);
}
private editVolume(volume: IVolume): void {
this.createMyVolumeForm.patchValue({
id: volume.id,
volumeInfo: {
title: volume.volumeInfo.title,
publisher: volume.volumeInfo.publisher,
authors: this.fb.group(this.authors),
publishedDate: volume.volumeInfo.publishedDate,
pageCount: volume.volumeInfo.pageCount,
imageLinks: {
thumbnail: volume.volumeInfo.imageLinks.thumbnail,
}
}
});
}
get authors(): FormArray {
return this.createMyVolumeForm.get('volumeInfo.authors') as FormArray;
}
addMoreAuthors() {
this.authors.push(this.fb.control(''));
}
}```
HTML:
<section class="form-holder">
<h2 class="form-heading">Create Volume</h2>
<form [formGroup]='createMyVolumeForm'>
<div class="input">
<label class="required-input" for="id">Id</label> <input id="id" type="text" formControlName="id" name="id"/>
</div>
<div formGroupName="volumeInfo">
<div class="input-holder">
<label class="required-input" for="title">Title</label>
<div class="input">
<input id="title" type="text" formControlName="title" name="title"/>
</div>
<button type="submit" class="button" (click)="addMoreAuthors()">Add Authors</button>
<div formArrayName="authors">
<div *ngFor="let author of authors.controls; let i = index;">
<label>Authors</label> <input type="text" [formControlName]="i">
</div>
</div>
<label class="required-input" for="publisher">Publisher</label>
<div class="input">
<input id="publisher" type="text" formControlName="publisher" name="publisher">
</div>
<label class="required-input" for="publishedDate">Published Date</label>
<div class="input">
<input id="publishedDate" type="text" formControlName="publishedDate" name="publishedDate">
</div>
<label class="required-input" for="pageCount">Page Count</label>
<div class="input">
<input id="pageCount" type="number" formControlName="pageCount" name="pageCount">
</div>
<div formGroupName="imageLinks">
<label class="required-input" for="thumbnail">Thumbnail</label>
<div class="input">
<input id="thumbnail" type="text" formControlName="thumbnail" name="thumbnail">
</div>
</div>
</div>
<div class="login-button-holder">
<input class="login-button"
type="submit"
[disabled]="createMyVolumeForm.invalid"
(click)="createMyVolume()" value="Create"/>
</div>
</div>
</form>
</section>
FormArrays have a confusing API. Rather than being an a FormControl representing an array value , they represent an array of FormControls. So if you want to assign a set of authors to the form, each of which is editable, then you need to create a new control for each one, and add it to the FormArray.
Taking this as an example:
private editVolume(volume: IVolume): void {
this.createMyVolumeForm.patchValue({
id: volume.id,
volumeInfo: {
title: volume.volumeInfo.title,
publisher: volume.volumeInfo.publisher,
authors: this.fb.group(this.authors),
publishedDate: volume.volumeInfo.publishedDate,
pageCount: volume.volumeInfo.pageCount,
imageLinks: {
thumbnail: volume.volumeInfo.imageLinks.thumbnail,
}
}
});
}
One method is, where you are assigning to authors, instead do authors: new FormArray([])
.
Then after patching the value to the form, do something like:
(this.createMyVolumeForm.get('authors') as FormArray).clear();
this.authors.forEach(a => {
const control = new FormControl(a);
(this.createMyVolumeForm.get('authors') as FormArray).add(control);
});
Hopefully that gets you on the right track.
Thank you Jesse, your answer really put me on the right track with a little tweek:
showExistingAuthors(volume: IVolume): void {
(this.createMyVolumeForm.get('volumeInfo.authors') as FormArray).clear();
volume.volumeInfo.authors.forEach(a => {
const control = new FormControl(a);
(this.createMyVolumeForm.get('volumeInfo.authors') as FormArray).push(control);
});
}```
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.