Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 5 form validation (required) not working

Tags:

I am learning Angular 5 with TypeScript. I am completely new to it. I am now trying to construct a form and validating it. But it is not working properly.

This is my component:

@Component({
    selector: 'app-login',
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.scss'],
    animations: [routerTransition()]
})
export class LoginComponent implements OnInit {

    loginForm: FormGroup;

    errors = [];

    constructor(private fb: FormBuilder, public router: Router, private globals: GlobalsService, private http: Http) {

    }

    ngOnInit() {
        this.loginForm = new FormGroup({
            email: new FormControl("", Validators.required),
            password: new FormControl("")
        });
    }

    onLoggedin(formData) {
        
        alert("Submit form");
  
  
    }

}

As you can see I am setting "required" validation attribute on the email field. This is my html.

<div class="login-page" [@routerTransition]>
    <div class="row justify-content-md-center">
        <div class="col-md-4">
            <img src="assets/images/logo.png" width="150px" class="user-avatar" />
            <h1>Yo Cash Flow</h1>
            <div class="alert alert-danger" *ngFor="let error of errors">
                <strong>{{ error.msg }}</strong>
            </div>
            <form [formGroup]="loginForm" role="form" (ngSubmit)="onLoggedin(loginForm.value)">
                <div class="form-content">
                    <div class="form-group">
                        <input type="text" name="email" formControlName="email" class="form-control input-underline input-lg" placeholder="Email">
                        <div *ngIf="loginForm.controls['email'].errors.required" class="text-danger">Email is required</div>
                    </div>

 
                </div>
                <button type="submit" class="btn rounded-btn"> Log in </button>
                &nbsp;
                <a class="btn rounded-btn" [routerLink]="['/signup']">Sign up</a>
            </form>
        </div>
    </div>
</div>

As you can see I am trying to show the error individually. I mean for "required" attribute, I am retrieving the error message like this errors.required. But it is not working. But when I tried to use "valid" like below, it is working.

loginForm.controls['email'].invalid

But I want to retrieve the error individually because I want to show the different message for the different error. How can I fix this? Why it is not working when I use loginForm.controls["email"].errors.required? What is the correct way of showing the different message for the different validation rule?

like image 727
Wai Yan Hein Avatar asked Dec 30 '17 19:12

Wai Yan Hein


People also ask

What is dirty in angular?

When the user changes the value in the watched field, the control is marked as "dirty" When the user blurs the form control element, the control is marked as "touched"

What is difference between touched and dirty in angular?

The difference between touched and dirty is that with touched the user doesn't need to actually change the value of the input control. touched is true of the field has been touched by the user, otherwise it's false. The opposite of touched is the property untouched .

What is AbstractControl in angular?

It provides some of the shared behavior that all controls and groups of controls have, like running validators, calculating status, and resetting state. It also defines the properties that are shared between all sub-classes, like value , valid , and dirty . It shouldn't be instantiated directly.


2 Answers

You can use the errors property, like so:

loginForm.controls['email'].errors

If there are no errors, it will return null, otherwise it will return an object like so:

{ required : true }

Then you simply need to create a function that will return a human readable error message, like so:

getErrorMessage(controlName, displayName) {
    let result = "";
    let errors  = loginForm.controls[controlName].errors;
    if (errors.required) {
        result += (displayName + " is required.");
    }
    if (errors.whatever) {
        result += "Whatever you like";
    }
    return result;
}
like image 78
user184994 Avatar answered Nov 15 '22 03:11

user184994


I have just spent a couple of hours trying to debug this problem in my project, the problem in my case turned out to be using:

<input type="checkbox" formControlName="testing" />

instead of:

<input type="checkbox" [formControl]="form.controls['testing']" />

In my case the FormControl "testing" is dynamically added using form.AddControl() - the second way of performing the name binding also binds the model to the input.

Hoping this can help someone with this issue!

like image 29
J. Madeley Avatar answered Nov 15 '22 03:11

J. Madeley