I am new to Angular and I am trying to build a UI with a form where one field is constant and 5 other fields should be displayed (appended) to the existing form with a click of a button and the user can add only 4 times at max and should be saved in the DB we are using .Net core for that and only first set has required fields. I tried to use the examples from the internet but it is not working.There are custom components being used in the UI so cannot add any input elements Need help <div class="client-report-controls"> <form *ngIf="!!clientreportForm" ctDynamicForm="clientreportForm" [formGroup]="clientreportForm"> <fieldset> <div class="mx-3"> <div class="col"> <div class="col-md-12"> <app-generic-input controlName="CompanyName"> </app-generic-input> </div> <div formArrayName="clientreportArray"> <div *ngFor="let clientreportGroup of clientreportArray?.controls; let i=index" [formGroupName] = "i"> <div class="col-md-12"> <app-generic-input controlName="Client"> </app-generic-input> </div> <div class="col-md-12"> <app-generic-input controlName="ClientLocation"> </app-generic-input> </div> <div class="h4"> File <button type="button" mat-button (click)="upload(1)" > <mat-icon>file_upload</mat-icon> <span>Choose File</span> </button> </div> <ul *ngIf="clientreportDocs?.length > 0"> <app-uploaded-attachment *ngFor="let document of clientreportDocs" [document]="document" [canDelete]="true" (deleted)="onDocumentDeleted($event,1)" ></app-uploaded-attachment> </ul> <div class="col-md-12"> <app-generic-input controlName="AdditionalInfo"> </app-generic-input> </div> </div> </div> <button (click)="addClientForm()">Add Client</button> <div class="client-report-subbuttons"> <button class="btn btn-primary" (click)="onSubmit()" [disabled]=" reCaptcha == null"> Submit </button> <button class="btn btn-outline"> Reset </button> </div> </div> </fieldset> </form> </div> </div> @Component({ selector: 'app-client-sharing', templateUrl: './client-report.component.html', styleUrls: ['./client-report.component.scss'], }) export class ClientreportFormComponent implements OnInit, OnDestroy { private unsubscribe$ = new Subject<void>(); ClientreportForm: FormGroup; dataUrl: string; selectedDocumentTypeId: DocumentTypeId; reCaptcha: string; reCaptchaSiteKey: string; columns: DatatableColumn[]; @ViewChild('fileInput', { static: false }) fileInput: ElementRef<HTMLInputElement>; ClientreportDocs : Document[] = []; constructor( private formService: FormInfoCacheService, private httpUrls: HttpUrls, private snackbarService: SnackbarService, private formCache: FormInfoCacheService, private formsPreloader: DynamicFormsPreloaderService, private ClientreportService: ClientreportService, private router:Router, private env: EnvironmentService ) { this.reCaptchaSiteKey = this.env.getEnvironment().reCaptchaSiteKey; } ngOnInit() { this.formsPreloader .ensureFormsLoaded(['ClientreportForm']) .pipe(takeUntil(this.unsubscribe$)) .subscribe({ next: (_) => { this.ClientreportForm = this.formCache.getFormGroup( 'ClientreportForm' ).formGroup; }}); this.ClientreportForm = new FormGroup({ ClientreportArray: new FormArray([ new FormGroup({ Position: new FormControl(''), ClientLocation: new FormControl(''), ClientRegion: new FormControl(''), }) ]) }); } ngOnDestroy() { this.unsubscribe$.next(); this.unsubscribe$.complete(); } upload(documentTypeId: DocumentTypeId) { this.selectedDocumentTypeId = documentTypeId; this.showFileDialog(); } onDocumentDeleted(documentId: number,documentTypeID:number) { if(documentTypeID == 1) { this.ClientreportDocs = this.ClientreportDocs.filter((d) => d.documentId !== documentId); } this.snackbarService.openSnackBarSuccess('Document deleted successfully'); } onFileSelected(data){ const file = data.files[0]; const documentUploadRequestocument = { entityId: 1, documentTypeId: 1, file: file, fileName:file.name, uploadedBySystemUserId:1, documentId : this.ClientreportDocs.length +1 , }; if(this.selectedDocumentTypeId == 1) { this.convertFile(file).subscribe((base64)=>{ this.ClientreportDocs[0].file = base64 }) this.ClientreportDocs.push(documentUploadRequest); } this.fileInput.nativeElement.value = ''; } showFileDialog(): void { this.fileInput.nativeElement.click(); } convertFile(file: File): Observable<string> { const result = new ReplaySubject<string>(1); const reader = new FileReader(); reader.readAsBinaryString(file); reader.onload = (event) => { result.next(btoa(event.target.result.toString())); }; return result; } onSubmit() { const ClientreportForm = { companyName: this.ClientreportForm.value.companyName, Position: this.ClientreportForm.value.position, ClientLocation: this.ClientreportForm.value.clientLocation, ClientRegion: this.ClientreportForm.value.clientRegion, reCaptcha : this.reCaptcha, documents: this.ClientreportDocs.length > 0 ? [ { documentId :0, formId:0, DocumentTypeId:3, fileBytes:this.ClientreportDocs[0].file, fileName:this.ClientreportDocs[0].fileName } ]:null }; } reCaptchaResolved(event: any) { this.reCaptcha = event; } handleError(error) { this.snackbarService.openSnackBarFailure( ServiceHelpers.getErrorMessage( error, 'An error occured.' ), 7500 ); } //added get ClientreportArray(): FormArray { return this.ClientreportForm.get('ClientreportArray') as FormArray; } addclientform() { this.ClientreportArray.push( new FormGroup({ Position: new FormControl(''), ClientLocation: new FormControl(''), ClientRegion: new FormControl(''), EmployersAffiliation: new FormControl('') }) ); } } Continue reading...