this is my first question, so I hope I prepared it well enough to explain the problem exactly. I've also created a stackblitz example for my problem
I receive the following string from our backend, which should be displayed in a table. ('1,2,[email protected],22.5,27.5@,,'
or '10,8,5,3,[email protected],25,32,47,63@2,2,1,0,'
). The length can vary. It is 3 parameters (separated by @) and the respective iteration and its values (separated by ,).
At the moment I use the [value]
accessor and the change
method to split the string and reassemble it. I would now like to use a validator for the respective values, which only works in conjunction with formControlName. (I know it works with ngModel too, but this is just an excerpt and we're already using the forms module for the other attributes).
I wrote a validator which is used in the first input field in my example and works as desired (later on several regex will follow, but for the example I chose only a simple one).
My question is: Is it possible to split the string and cast it into FormControls? How do I then access it and display it in HTML?
I know FormArrays, but couldn't quite get the hang of it, since this is a FormArray within a FormArray (I guess? -One for the parameters and one for the iteration values)
My next approach would be to include the validation for the input in my current setBlockValue method, which sets an .invalid class on the element and then displays an error text below the input field. But then that still doesn't help me mark the form as invalid when submitting.
I hope this is clear enough and that my stackblitz example is helpful. I am very thankful for any resources (like other questions or articles) that may solve my problem. I just did not find any fitting yet.
Not exactly got your data structure, but seems you need something like this (we use ReactiveForms) TS:
import { Component } from '@angular/core';
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title="Stack Overflow"
form: FormGroup;
blockValue = '10,8,5,3,[email protected],25,32,47,63@2,2,1,0,';
params = ['param1', 'param2', 'param3'];
constructor(
private _fb: FormBuilder
) {
//can be simplify, depend on aims
this.form = _fb.group({
block: _fb.array([])
});
}
get block(): FormArray {
return this.form.get('block') as FormArray;
}
ngOnInit(): void {
this._buidForm();
this.block.valueChanges
.subscribe(values => {
console.log(values);
})
}
private _buidForm(): void {
const data = this.blockValue.split('@').map(col => col.split(','));
for (let i = 0; i < data[0].length; i++) {
const group = this._fb.group({});
this.params.map((param, idx) => {
const control = this._fb.control(data[idx][i], Validators.required); //or other validators
group.addControl(param, control)
});
this.block.push(group);
}
}
onSubmit(): void {
console.log(this.form.value);
}
}
HTML:
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<table formArrayName="block">
<tr>
<td *ngFor="let param of params">{{param}}</td>
</tr>
<tr *ngFor="let group of block.controls; let i = index;" [formGroupName]="i">
<td *ngFor="let col of params">
<input type="text" [formControlName]="col" [style.background]="block.controls[i].get(col)?.invalid ? 'pink':'white'">
</td>
</tr>
</table>
<button type="submit" [disabled]="form.invalid">CHECK</button>
</form>