Daniel
Daniel

Reputation: 1995

angular dynamic required inputs doesn't affect form.invalid property

I have these form inputs that I generate with *ngFor after clicking a button. in these inputs, I put the required attribute but it seems like it doesn't affect the form.invalid I got other required inputs that aren't generated dynamically and when they're not filled with values the submit button is disabled as I want it to be, so I guess the issue is that the dynamic inputs doesn't exist until I click the button.

In addition I didn't manage to bind these inputs since they're dynamic, and I want to get they're values and send to a service when submitting the form. any suggestions how to do such a thing?

EDIT

I've added to my model object in component.ts this this.model.players = Array(this.model.numOfTeams*this.model.numOfPlayers).fill(new Result()) and to my html i added ngModel 2way binding. now the validation is working fine, but all of the fields with same name (for example firstName) are changed together when I type in one of them.

here is my component.html:

<div class="container">
    <form #newSearch="ngForm" class="form" ngNativeValidate>
        <div class="form-group pl-3">
            <fieldset name="generatePlayerCards">
                <legend>generatePlayerCards</legend>
                <p>Please choose <b>number of teams</b> and <b>number of players for each team</b>:</p>
                <input class="form-control mt-3" type="number" name="numOfTeams" id="numOfTeams" min="1" max="5" placeholder="Number of teams" [(ngModel)]="model.numOfTeams" required>
                <input class="form-control mt-3" type="number" name="numOfPlayers" id="numOfPlayers" min="1" max="20" placeholder="Number of players for each team" [(ngModel)]="model.numOfPlayers" required>
                <button class="btn btn-primary mt-3" type="button" (click)="generatePlayerCards()">Done</button>
            </fieldset>
        </div>
        <div class="card-group">
            <div *ngFor="let j of ngArr; let i = index; trackBy:trackByIndex;" class="col-4 mt-3">
                <div class="card">
                    <div class="card-header text-left"><h5>New Player Data</h5></div>
                    <div class="card-body">
                        <label for="firstName{{i}}"></label>
                        <input type="text" name="firstName{{i}}" class="form-control my-1 mr-sm-1" autocomplete="off" placeholder="First Name" required [(ngModel)]="model.players[i].firstName">
                        <label for="lastName{{i}}"></label>
                        <input type="text" name="lastName{{i}}" class="form-control my-1 mr-sm-1" autocomplete="off" placeholder="Last Name" required [(ngModel)]="model.players[i].lastName">
                        <label for="score{{i}}"></label>
                        <input type="text" name="score{{i}}" class="form-control my-1 mr-sm-1" autocomplete="off" placeholder="Score" required [(ngModel)]="model.players[i].score">
                    </div>
                </div>
            </div>
        </div>
        <div class="col-3 mt-4">
            <button [disabled]="newSearch.form.invalid" class="btn btn-primary mr-2" type="submit" (click)="search()">Submit</button>
            <button class="btn btn-secondary" type="reset" (click)="resetForm()">Clear Form</button>
        </div>
    </form>
</div>

Upvotes: 2

Views: 536

Answers (1)

Filas Siuma
Filas Siuma

Reputation: 321

In Angular in order to have dynamic fields and validation it is best practice to do it using a Form Array.

It might seem complicated at first, but Reactive forms in Angular are an incredible tool that will let you achieve great results with little to no effort in future. There are plenty video tutorials, this one is the best imho.

Upvotes: 1

Related Questions