How to enable a button once all form fields pass - javascript

My first Angular 5 app.
I've read through: https://angular.io/guide/form-validation and several pages I googled to find the answer, only to find that they're all really out of date.
I have multiple input boxes on my form like:
<form name="pizzaPlaceForm" class="form-container">
<mat-form-field>
<input matInput placeholder="Shop Name" [(ngModel)]="pizzaPlace.shopName"
id="shopName" name="shopName" #shopName="ngModel"
required minlength="4">
<mat-error>You must provide a shop name at least 4 characters in length.</mat-error>
</mat-form-field>
<br/>
<mat-form-field>
<input matInput placeholder="Contact Name" [(ngModel)]="pizzaPlace.contactName"
id="contactName" name="contactName" #contactName="ngModel"
required minlength="4">
<mat-error>You must provide a contact name at least 4 characters in length.</mat-error>
</mat-form-field>
</form>
Now I want to control the disabled state of my button and only enable it when all of the required fields have been entered, like:
<button mat-raised-button disabled="pizzaPlaceForm.$invalid" (click)="onCreateClick()" *ngIf="createMode">Create</button>
Only it doesn't appear that $invalid works any more, so how do I do this with Angular 5?

you want to disable the button if the form is not valid. so you can try below
<button mat-raised-button [disabled]="!pizzaPlaceForm.valid" (click)="onCreateClick()" *ngIf="createMode">Create</button>

Add an identifier for the form with an ngForm. Then you can disabled the submit button
with [disabled] attribute.
[disabled]="pizzaPlace.form.invalid" OR [disabled]="pizzaPlace.invalid"
<form #pizzaPlace="ngForm" name="pizzaPlaceForm" class="form-container">
<button mat-raised-button [disabled]="pizzaPlace.form.invalid" (click)="onCreateClick()" *ngIf="createMode">Create</button>
</form>

Related

How to disable button if there is no input entered including space char in Angular

I have a simple input field and 1 button for save it. If the input field is empty, then button becomes disabled. But with my code, space character is acting like normal character so user can enter value by just putting space. How can i check at least 1 char exist on input field?
the code:
<mat-form-field fxFlex="50">
<input matInput name="postalAddress"
[(ngModel)]="employee.postalAddress" placeholder="Postal Address"
required>
</mat-form-field>
<button type="button" id="save" class="button-style" (click)="onSaveOffice()"
[disabled]="!employee.postalAddress" > Save
</button>
Note: I am using typescript at back so do i need to do any logic at typescript code ?
You can use trim() method on string before checking emptiness, so it will remove all the spaces:
<mat-form-field fxFlex="50">
<input matInput name="postalAddress"
[(ngModel)]="employee.postalAddress" placeholder="Postal Address"
required>
</mat-form-field>
<button type="button" id="save" class="button-style" (click)="onSaveOffice()"
[disabled]="!employee.postalAddress?.trim()" > Save
</button>
Hope that helps.

Angular - Template driven form - Email validation not happening

I am making a simple template-driven form with 'Email Validation' in it (Not by Reactive Forms). So, required, minlength, maxlength are working fine. But, when I try email to be valid, its failing. Can someone help me out?
abc.component.html
<form #customForm="ngForm" (ngSubmit)="alpha(customForm)">
<input type="text" name="firstName" ngModel #firstName ="ngModel" required minlength="3" maxlength="10"><br/>
<div *ngIf="firstName.touched">
<p *ngIf="firstName.errors?.required">First Name is Required!!!</p>
<p *ngIf="firstName.errors?.minlength">First Name minimum 3 characters are required!!!</p>
<p *ngIf="firstName.errors?.maxlength">First Name max length is 10!!!</p>
</div>
<input type="email" name="email" ngModel #email="ngModel" required><br/>
<div *ngIf="email.touched">
<p *ngIf="email.errors?.required">Email is a required field!</p>
<p *ngIf="email.errors?.email">This is not a valid Email!!!</p>
</div>
<button type="submit" [disabled]="customForm.invalid">Submit</button>
</form>
Note: Though required validation of email is taking place, but as the
pattern or data entered is not correct, the 2nd validation in email
validation div must give error.
Result: (Email valid and its pattern not automatically giving error)
You could add an email attribute to your Email Input. But then that would not in-validate it for something of the pattern xxx#xxx which I think would not be a valid email in your case.
I suggest you use pattern="[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$" instead. Then, where you're showing the error message, you should check for email.errors?.pattern instead.
Give this a try:
<input
type="email"
name="email"
ngModel
#email="ngModel"
pattern="[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$"
required>
<br/>
<div *ngIf="email.touched">
<p *ngIf="email.errors?.required">Email is a required field!</p>
<p *ngIf="email.errors?.pattern">This is not a valid Email!!!</p>
</div>
Try both the approaches on this Sample StackBlitz and use the one that suits you better.
Replace this line
<input type="email" name="email" ngModel #email="ngModel" required>
with
<input type="email" name="email" ngModel #email="ngModel" required email>// add email attribute
use "pattern = regrex" in input tag and use validation email?.errors?.pattern

Angular 2+ multi-part form validation, how to check validity of single input

I have a form, and the form has multiple inputs that are all bound to different variables. Before submitting the form, I need to do validity checks, pristine checks, etc. For example, I want my submit button to be disabled if every part of the form is pristine, or if something is invalid.
Using Angular 5, I am trying to get access to the .pristine, .valid, and .invalid flags for each input field, but the values are either undefined or "cannot get .pristine of undefined".
I am able to get these flags on the entire form itself, but this doesn't help, because I want to know how to get it for each individual input.
Here is my current code (I've removed a number of my inputs to simplify the example).
<form #editDetailsForm="ngForm" name="editDetailsForm" >
<label for="name"> Name </label>
<input type="text" id="name" name="name" maxlength="40" [(ngModel)]="myName" required />
<label for="description"> Description </label>
<textarea id="description" name="description" maxlength="250" [(ngModel)]="myDescription" required ></textarea>
<button id="submit" type="button"
[disabled]="saveButtonDisabled(editDetailsForm.invalid, editDetailsForm.name.invalid, editDetailsForm.description.invalid)"
(click)="updateDetails()" >
Save
</button>
</form>
If you see, I bind disabled attribute on the Save button to saveButtonDisabled() function, where I want to pass in information about each input's validity. The first argument, editDetailsForm.invalid returns a true or false, but the other values return undefined.
How do I check validity of these individual inputs?
EDIT: I realize I can derive all of this info inside my component because all of the input values are bound. However, it'd be easier just to check a flag or two.
I'm not sure I totally understand what you want to do, but this is how you get access to the form controls .pristine, .invlaid
<input type="text" id="name" name="name" #name="ngModel" maxlength="40" [(ngModel)]="myName" required />
The #name="ngModel" sets a template reference to the FormControl angular creates
Then you should be able to do something like this:
<input type="text" id="name" name="name" #name="ngModel" maxlength="40" [(ngModel)]="myName" required />
<div *ngIf="name.pristine">
Name is Pristine
</div>
Just to clarify, the individual form fields bubble up to the form itself. So if any field has been touched, then the whole form will be pristine == false.
You can access the input controls using the .controls property, like:
<button id="submit" type="button"
[disabled]="editDetailsForm.controls.name?.invalid || editDetailsForm.controls.description?.invalid">
Created a stackblitz. https://stackblitz.com/edit/angular-5ir4k7
Added template reference variable for ngModel and validate using isValid.

Angular 5 required form fields not working with material

My first Angular app with Angular 5.
I am following the documentation here: https://angular.io/guide/form-validation. Here is the form that I created:
<form class="form-container">
<mat-form-field>
<input matInput placeholder="Shop Name" [(ngModel)]="pizzaPlace.shopName"
id="shopName" #shopName="ngModel"
required minlength="4">
</mat-form-field>
<div *ngIf="shopName.invalid && (shopName.dirty || shopName.touched)"
class="alert alert-danger">
<div *ngIf="shopName.errors.required">
Shop name is required.
</div>
<div *ngIf="shopName.errors.minlength">
Shop name must be at least 4 characters long.
</div>
</div>
<br/>
<mat-form-field>
<input matInput placeholder="Contact Name" [(ngModel)]="pizzaPlace.contactName"
id="contactName" #contactName="ngModel"
required minlength="4">
</mat-form-field>
</form>
So now if I read the docs correctly, entering and leaving the shop name field will generate an error, but it doesn't seem to be working. I get no indication whatsoever that there's any kind of a problem at all.
Template driven forms need a name attribute.
<input matInput placeholder="Shop Name" [(ngModel)]="pizzaPlace.shopName"
id="shopName" #shopName="ngModel"
required minlength="4"
name="shopName">
https://stackblitz.com/angular/eqormqnlkme
I would recommend strongly to use reactive forms, they aren't more difficult to master, but much more powerful.
Also, angular-material provides a built in component for error handling:
mat-error
you need to add a component to display the error
<mat-form-field>
<input matInput placeholder="Shop Name" [(ngModel)]="pizzaPlace.shopName"
id="shopName" #shopName="ngModel"
required minlength="4">
<mat-error>I said required !</mat-error>
</mat-form-field>

Setting form and inputs to "ng-dirty" programatically

I've never worked with Angular or Angular2 before, but now I have to make an update to a site running on my domain that is using Angular2. I need to programatically fill out a textbox and click submit, but after setting the textbox's value using .value = "val", it still treats the textbox as if it is empty.
I've read up on angular and now understand the concept of ng-dirty and ng-pristine, but programatically changing the class to ng-dirty still doesn't work.
It seems like even if I change the classes, it is still not updating the "pristine" status and it still considers the textbox empty.
I've read about "markAsDirty()" and tried using it but I get "markAsDirty is not a function". I just need to figure out how to update the page so that it realizes that the textbox is not empty and lets me submit the form.
Thanks a lot!
Edit:
Page form:
<form id="form_register" novalidate="">
<div class="form-steps">
<div class="form-group">
<div class="input-group">
<input autocomplete="off" class="form-control ng-pristine ng-invalid ng-touched" data-is-regex="true" data-mask="[a-zA-Z0-1\.]+" id="username" name="username" ngcontrol="username" placeholder="Username" required="" style="color: black !important;" tabindex="13" type="text">
</div>
</div>
<div class="form-group">
<div class="input-group">
<input autocomplete="off" class="form-control ng-untouched ng-pristine ng-invalid" id="password" name="password" ngcontrol="password" placeholder="Password" required="" style="color: black !important;" tabindex="14" type="password">
</div>
</div>
<div class="form-group">
<button class="btn btn-block btn-lg btn-info" tabindex="4" type="submit">
Log In
</button>
</div>
</div>
</form>
My problem is that this:
document.getElementById("username").value = "testuser";
document.getElementById("password").value = "testpass";
document.getElementsByClassName("btn btn-block btn-lg btn-info")[0].click();
ends up giving me a message saying the username and password are required even though there is a value showing in the textbox. Simply clicking on the textbox, typing a character, then deleting it will allow me to submit the form, but I need to accomplish this without user interaction.
You are filling the forms with native javascript and that is not updating the angular model. In your backing component you need to use ngmodel to connect your elements to the component. Then update the variables in the component and everything will reflect correctly.
Okay, there are a few issues with your code that I can see and I'll walk through getting this to work as expected.
For a Template driven form, create and assign the form group variable (which will make our shiny NgForm which we later attach controls to with ngControl) in the template, and lets bind the submit function while we're at it:
<form #myForm="ngForm" (ngSubmit)="submit(myForm.value)" id="form_register" novalidate="">
Each of our inputs is standalone and not yet tied to the form, to do so we'll want to clear the ng- classes which should be managed by Angular 2 and add our [(ngModel)] binding to a property.
<input autocomplete="off" class="form-control" data-is-regex="true" data-mask="[a-zA-Z0-1\.]+"
id="username" name="username" placeholder="Username" ngControl="username" [(ngModel)]="username"
required style="color: black !important;" tabindex="13" type="text">
We're going to disable our submit if the form is invalid:
<button [disabled]="myForm.invalid" class="btn btn-block btn-lg btn-info" tabindex="4" type="submit">Log In</button>
Our class has the username and password properties that we bind to, and our submit function:
export class App {
password: string;
username: string;
submit(value) {
console.log("submitting: " + JSON.stringify(value));
}
}
Finally, if we really want to mark things dirty programmatically this way we will have to grab our template variable in our code with a ViewChild:
#ViewChild('myForm') formGroup;
password: string;
ngAfterContentInit() {
this.formGroup.control.markAsDirty();
}
To do it per control we either need to access it through our formGroup variable or add individual template variables on the inputs we can grab with [(ngModel)]="username" #username="ngModel", for instance.
here's a plunker you can play with to try and develop your understanding: http://plnkr.co/edit/ukJ1kq2UFBvtoCsxbyba?p=preview

Categories

Resources