Reputation: 658
I have the following form that lists questions and have an answer field. the questions listed by a loop from api and all of them need to have the same field name. Everything works fine, the problem is I can't submit all the form values except the last one. Is there any way to use a form control name for multiple fields.
move-maker-add-component.ts
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroupDirective, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';
import { ApiService } from 'src/app/shared/services/api.service';
import { AuthService } from "src/app/shared/services/auth.service";
import { Router } from '@angular/router';
@Component({
selector: 'app-move-makers-add',
templateUrl: './move-makers-add.component.html',
styleUrls: ['./move-makers-add.component.scss']
})
export class MoveMakersAddComponent implements OnInit {
moveMakerForm: FormGroup;
moveMakerId:any;
moveMakers:any='';
answer:any;
id:string='';
constructor(public authService: AuthService,private router: Router, private api: ApiService, private formBuilder: FormBuilder) { }
ngOnInit() {
this.getMoveMaker();
this.moveMakerForm = this.formBuilder.group({
'moveMakerId' : [null, Validators.required],
'answer' : [null, Validators.required],
});
}
getMoveMaker() {
this.api.getMoveMakers().subscribe(data => {
this.moveMakers = data;
});
}
onFormSubmit(form:NgForm) {
this.api.addMoveMaker(form)
.subscribe(res => {
this.router.navigate(['/dashboard']);
}, (err) => {
console.log(err);
});
}
}
move-maker-add.component.html
<app-header></app-header>
<!-- partial -->
<div class="container-fluid page-body-wrapper">
<!-- partial:partials/_sidebar.html -->
<app-nav></app-nav>
<!-- partial -->
<div class="main-panel">
<div class="content-wrapper">
<div class="row">
<div class="col-8 grid-margin stretch-card offset-2">
<div class="card">
<div class="card-body">
<h4 class="card-title" style="text-align:center;">{{ 'MOVE_MAKERS' | translate }}</h4>
<form class="forms-sample" [formGroup]="moveMakerForm" (ngSubmit)="onFormSubmit(moveMakerForm.value)">
<div class="form-group" *ngFor="let moveMaker of moveMakers">
<label for="exampleTextarea1">{{moveMaker.question}}</label>
<input type="text" class="form-control" formControlName="moveMakerId" id="exampleInputName1" value="{{moveMaker.id}}" >
<textarea class="form-control" id="exampleTextarea1" formControlName="answer" rows="4"></textarea>
</div>
<button class="btn btn-light">{{ 'CANCEL' | translate }}</button>
<button type="submit" class="btn btn-gradient-primary mr-2">{{ 'SAVE' | translate }}</button>
</form>
</div>
</div>
</div>
</div>
<!-- content-wrapper ends -->
<!-- partial:../../partials/_footer.html -->
<!-- partial -->
</div>
<!-- main-panel ends -->
</div>
<!-- page-body-wrapper ends -->
</div>
<!-- container-scroller -->
<!-- plugins:js -->
<script src="../../vendors/js/vendor.bundle.base.js"></script>
<script src="../../vendors/js/vendor.bundle.addons.js"></script>
<!-- endinject -->
<!-- inject:js -->
<script src="../../js/off-canvas.js"></script>
<script src="../../js/misc.js"></script>
<!-- endinject -->
<!-- Custom js for this page-->
<script src="../../js/file-upload.js"></script>
<!-- End custom js for this page-->
<app-footer></app-footer>
MoveMaker.ts
export class UserMoveMaker {
answer : any;
moveMakerId : any;
}
Upvotes: 2
Views: 22149
Reputation: 21
The implementation made is the mixture of Reactive form and Template Driven. Would be better if you could follow any one approach.
With respect to reactive form approach, this can be achieved using FormArray. Example - https://stackblitz.com/edit/angular-material-editable-table-fazhbc?file=src%2Fapp%2Fapp.component.html
With respect to template driven forms, replace your (ngSubmit)="onFormSubmit(moveMakers)"
Upvotes: 2
Reputation: 3149
I usually add the formControlName dynamically with different values and then add the validators in the .ts file if needed. In this case It would look like this:
move-maker-add.component.html
<input type="text" class="form-control" [formControlName]="moveMaker.id" id="exampleInputName1" value="{{moveMaker.id}}" >
move-maker-add-component.ts
getMoveMaker() {
this.api.getMoveMakers().subscribe(data => {
this.moveMakers = data;
this.moveMakers.forEach((moveMaker ) => this.moveMakerForm .addControl(moveMaker.id, new FormControl('', Validators.required)));
});
}
Upvotes: 6