1
votes

The issue that I am having is that I am not getting the expected functionality out of my *ngIf statement inside an *ngFor. I am using it to iterate through custom validation messages and each ngIf has a unique statement. The following is the component.html file I am working with:

<div class="form-group">
<label for="{{title}}">First Name:</label>
<input type="text" class="form-control" id="{{title}}" name="{{title}}" [(ngModel)]="vm.title" [ngModelOptions]="{standalone: true}" #title="ngModel" minlength="{{minLength}}" maxlength="{{maxLength}}" required />
<div *ngIf="title.errors && (title.dirty || title.touched)" class="alert alert-danger">
    <div *ngFor="let validation of validations">
        <div *ngIf="validation.method">{{validation.message}}</div>
    </div>
</div>

And here is the component.ts file:

import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';

@Component({
    selector: 'textbox',
    templateUrl: './textbox.component.html',
    styleUrls: ['./textbox.component.css']
})

export class TextboxComponent implements OnInit {
    @Input('title') title: string;
    @Input('required') required: boolean;
    @Input('required-message') requiredMessage: string;
    @Input('min-length') minLength: number;
    @Input('min-length-message') minLengthMessage: string;
    @Input('max-length') maxLength: number;
    @Input('max-length-message') maxLengthMessage: string;
    validations: Validation[] = [];

    public vm: SignUp;

    ngOnInit() {
        this.vm = new SignUp();
        if (this.required) {
            if (this.requiredMessage[0] != "") {
                this.validations.push(new Validation(this.title + ".errors.required", this.requiredMessage));
            } else {
                this.validations.push(new Validation("!" + this.title + ".errors.required", "First name is required"));
            }
        } else {
            //make not required
        }
        if (this.minLength) {
            if (this.minLengthMessage) {
                this.validations.push(new Validation(this.title + ".errors.minlength", this.minLengthMessage));
            } else {
                this.validations.push(new Validation("!" + this.title + ".errors.minlength", "Minimun length is " + this.minLength));
            }
        }
        if (this.maxLength) {
            if (this.maxLengthMessage) {
                this.validations.push(new Validation(this.title + ".errors.maxlength", this.maxLengthMessage));
            } else {
                this.validations.push(new Validation("!" + this.title + ".errors.maxlength", "Maximun length is " + this.maxLength));
            }
        }
        for (var i = 0; i > this.validations.length; i++) {
            console.log(this.validations[i].method);
            console.log(this.validations[i].message);
        }
    }
}
export class SignUp {
    nameFirst: string;
    nameLast: string;
    username: string;
    password: string;
}
export class Validation {
    constructor(public method: string, public message: string) {
        console.log(method);
        console.log(message);
    }
}

I am calling the component from another component like this:

<div class="row">
    <form #form="ngForm">
        <div class="form-group">
            <textbox [title]="'nameFirst'" [required]="true" [required-message]="'required message test'" [min-length]="5" [min-length-message]="'minimum length test'" [max-length]="10" [max-length-message]="'maximum length test'"></textbox>
        </div>
    </form>
</div>

What ends up happening is that all the validation messages display regardless of whether they should be triggered. For example, "max length test" is showing even though I'm no where near the max # of characters.

Here is a plunkr to play around with the functionality: https://plnkr.co/edit/IgQ9WxSHVaTz7zz0aajU

2

2 Answers

0
votes
<div *ngIf="validation.method">{{validation.message}}</div>

You're having the message show as long as validation.method exists. Every time you create a Validation, you're doing it like this:

new Validation(this.title + ".errors.minlength", this.minLengthMessage)

The Validation's method property is a string and is never empty, so the *ngIf directive is always evaluating to true.

0
votes

What Jun Kang said. Also, it seems like you are doing an awful lot of work that you don't need to be. Have you looked into building Reactive Forms? Here's a short example:

  createForm() {
    this.heroForm = this.fb.group({
      name: ['', Validators.required ],
      street: ['', [Validators.minLength(6), Validators.required]]
    });
  }

Then you'd simply use an ngIf for each validator in your HTML. Walk through Angular's example. It's useful and your code will be easier to handle: https://angular.io/guide/reactive-forms