I'm new to the NgForm. So here's the code & below the scenario...
- I have an application where use has to enter multiple server paths.
- All the paths are stored in a list. UI populates all the paths using *ngFor. By default the list is initialized with a dumb entry
public list: any[];
this.list = [
{
path: '',
port: null,
},
];
So this is how the code looks like
<form #serverForm="ngForm">
<div *ngFor="let item of list; let i = index">
<input
type="text"
name="path{{ i }}"
id="path{{ i }}"
[value]="item.path"
[(ngModel)]="list[i].path"
/>
</div>
</form>
- Each path is a text field & each field is a control
- Control gets their name by name attribute
name="path{{ i }}"
& each control has a pattern validator attached to itpath: new FormControl('', [Validators.required, Validators.pattern(this.pattern)])
- Pattern can be of multiple types. E.g., here user can select one of the 2 patterns from UI
<div>
<label> Pattern Type </label><br />
<input type="radio" name="patternType" (change)="setPattern(1)" />String
<input type="radio" name="patternType" (change)="setPattern(2)" />Numbers
</div>
setPattern(v: number) {
if (v === 1) {
this.pattern = /[a-z] /;
} else if (v === 2) {
this.pattern = /[A-Z] /;
}
// setting formcontrol pattern validator
this.serverForm.controls['path0']?.addValidators(
Validators.pattern(this.pattern)
);
}
- As you can see, the last line is to attach a validator pattern to the first control
path0
- User tries entering new path by clicking on
Add new entry
button. This button has a method associated with it which will add a new field.<button (click)="addNewEntry()">Add new path</button>
adds a new dumb entry to the list & a new field comes up in the UI.
public addNewEntry() {
this.list.push({
path: '',
port: null,
});
}
- When *ngFor iterates over the list, name attribute which is unique because of the index, a new control gets automatically added to the NgForm serverForm
So what is the issue?
- Most important, how to detect dynamically that a new control is available in the form and I should attach a validator to it? I don't want to even hardcode the
path0
insetPattern()
in point 5 addNewEntry()
has no clue that a new control is added which makes difficult to add pattern validator inthis.pattern
. BecauseaddNewEntry()
executed beforethis.serverForm.valueChanges.subscribe
How to resolve this? Basically I want to dynamically attach a pattern validator to the newly generated control inside the NgForm
Also here is the code for the same.
CodePudding user response:
I would argue that you're taking the wrong approach. It is much easier to achieve the result you want with Reactive forms vs template-driven forms as you have attempted to do.
What is great about reactive forms is that they have their own built-in arrays, and you can push new form groups into them with whatever validation you want, like so:
public addNewEntry() {
const pattern = this.patternValue === '1' ? /[a-z] / : /[0-9] /;
this.serverArray.push(
this.fb.group({
path: [null, [Validators.pattern(pattern)]],
port: '',
})
);
}
StackBlitz here. I changed the validator regex because the other regex was for capital letters, not numbers.