html5 validation in Ionic - html

I am learning Ionic at the time. But it seems like HTML5 validation is not working in Ionic.
So, i have a login form like below.
<h3> Login </h3>
<form>
<input name="emailaddress" placeholder="Enter Email Address" class="email" [(ngModel)]="userData.l_email" type="email" required />
<input name="name" placeholder="Enter Password" class="name" type="password" [(ngModel)]="userData.l_password" required />
<button class="semi-transparent-button is-blue with-border" (click)="login()">
Login
</button>
</form>
When i click on login button it didn't perform validation. As i have put required in both field but it simply submit the form.
Also email validation is not working.
I have checked How can I make validation of email in Ionic using HTML5, JS or Angular work? but it is a work around. That i want to avoid.

HTML5 form validation does not work in Ionic. Instead, you can use Angular forms.
This is a great tutorial by Josh Morony on how to do it.
In your case, you can do something like this using FormBuilder and specifying Validators for each field (for a full list of available validators, take a look at the docs).
import { Component } from '#angular/core';
import { Validators, FormBuilder, FormGroup } from '#angular/forms';
#Component({
selector: 'page-login',
templateUrl: 'login.html'
})
export class Login {
login: FormGroup;
submitted: boolean = false;
constructor(public formBuilder: FormBuilder) {
this.login = this.formBuilder.group({
email: ['', Validators.compose([Validators.email, Validators.required])],
password: ['', Validators.required],
});
}
onLogin() {
this.submitted = true;
if (this.login.valid) {
console.log(this.login.value);
}
}
}
In your template, use FormGroup and show your error message when the field is invalid.
<form [formGroup]="login" (ngSubmit)="onLogin()">
<ion-item>
<ion-label>Email</ion-label>
<ion-input type="email" formControlName="email"></ion-input>
</ion-item>
<p ion-text [hidden]="login.controls.email.valid || submitted === false" color="danger" padding-left>
Please enter a valid email
</p>
<ion-item>
<ion-label>Password</ion-label>
<ion-input type="password" formControlName="password"></ion-input>
</ion-item>
<p ion-text [hidden]="login.controls.password.valid || submitted === false" color="danger" padding-left>
Password is required
</p>
<button ion-button type="submit">Login</button>
</form>

Related

How to show success or failure message in angular?

user.component.html
<form #ff="ngForm">
<input type="text" name="fname" placeholder="User Name" [(ngModel)] = "selectedUser.fname"/><br/><br/>
<input type="number" name="age" placeholder="age" [(ngModel)] = "selectedUser.age"/><br/><br/>
<input type="radio" name="sex" value="male" [(ngModel)] = "selectedUser.sex"/> Male<br/><br/>
<input type="radio" name="sex" value="female" [(ngModel)] = "selectedUser.sex"/> Female<br/><br/>
<input type="button" name="submit" value="submit" (click)="createUserData(ff.value)">
</form>
user.component.ts
import { Component, OnInit } from '#angular/core';
import { UserService } from '../../service/user.service';
#Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
constructor(private us:UserService) { }
user: any;
selectedUser: any = {fname:null, age: null, sex: null};
ngOnInit(): void {
}
createUserData(ff){
this.us.createform(ff).subscribe((user:any)=>{
console.log("Success register");
});
}
}
I am new in angular and I am trying to insert form data in database using web API to mysqli which is working fine. Now, I want to show success or failure message in my user.component.html page. I want when I click on submit button the page reload and show success or failure message. So, How can I do this please help me.
Thank you
You don't need to reload the page. You can choose to navigate to another component/page, or you can show a Popup dialog or you could render ad different content.
here a very simple example in order to render a different content:
registerSucess:boolean = false;
createUserData(ff){
this.us.createform(ff).subscribe((user:any)=>{
console.log("Success register");
this.registerSucess=true;
});
}
and in the tempalte:
<form #ff="ngForm" *ngIf="!registerSucess">
<input type="text" name="fname" placeholder="User Name" [(ngModel)] = "selectedUser.fname"/><br/><br/>
<input type="number" name="age" placeholder="age" [(ngModel)] = "selectedUser.age"/><br/><br/>
<input type="radio" name="sex" value="male" [(ngModel)] = "selectedUser.sex"/> Male<br/><br/>
<input type="radio" name="sex" value="female" [(ngModel)] = "selectedUser.sex"/> Female<br/><br/>
<input type="button" name="submit" value="submit" (click)="createUserData(ff.value)">
</form>
<h1 *ngIf="registerSucess"> Register Success :D </h1>
or you could use the variavle userinstead of registerSuccess, might be simpler
Create a string variable in user.component.ts to hold the message
export class UserComponent implements OnInit {
message = '';
...
Add an element to the html to contain the message, I'll use a <p>. Double curly brackets {{ }} allow you to insert a variable from the component.
<p>{{message}}</p>
Now simply updating the message in the component will update the html
createUserData(ff){
this.message = "Creating User Data..."
this.us.createform(ff).subscribe((user:any)=>{
this.message = "Success!"
});
}
In your code:
this.us.createform(ff).subscribe((user:any) => {
console.log("Success Register")
});
The code in the 'subscribe' delta function is executed every time a response is received through the 'createform' function. So here you can input some sort of mechanism to trigger you popup.
You need a popup window to be shown, which comes down to what sort of UI components you are using. The popup can be written in your html, and only shown through a flag that you activate in the subscribe delta function, and then disable when pressing or closing the popup.
I'd recommend using something like bootstrap for UI components.

Angular: Submit method executed by clicking another button

I'm using Angular with Angular Material components.
So, I added a login component (form) where the user can type in his email and password. The input field for the password has an eye on the end to enable the user to display the password in plain text if wanted.
Unfortunately, by clicking twice the eye button, the submit method executes which is binded to the submit button.
The simple question is: why?
Template
<form [formGroup]='loginForm' (ngSubmit)="onSubmit()">
<div>
<mat-form-field>
<mat-label for="email">E-Mail</mat-label>
<input matInput type="text" formControlField="email" />
<mat-error>
Test
</mat-error>
</mat-form-field>
</div>
<div>
<mat-form-field>
<mat-label for="password">Password</mat-label>
<input matInput [type]="hide ? 'password' : 'text'" formControlField="password" />
<button mat-icon-button matSuffix class="mat-icon-button mat-button-base" (click)="hide = !hide" [attr.aria-label]="'Hide password'" [attr.aria-pressed]="hide">
<mat-icon>{{ hide ? 'visibility_off' : 'visibility' }}</mat-icon>
</button>
</mat-form-field>
</div>
<button mat-raised-button color="primary" type="submit">Login</button>
Component
export class LoginComponent implements OnInit {
loginForm: FormGroup;
hide = true;
constructor(
private formBuilder: FormBuilder
) {
this.loginForm = this.formBuilder.group({
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required]]
})
}
onSubmit() {
window.alert("Login button clicked");
}
Try adding type="button" to your "eye" button.
This will tell the browser not to treat it as a submit button when inside a form.
The reason is that missing type argument from button is treated as default state and by default button element has submit.
The missing value default and invalid value default are the Submit Button state.
Source: https://html.spec.whatwg.org/multipage/form-elements.html#attr-button-type

Angular reactive FormGroup is not reset in third party controls

I am using Angular6 and angular material stepper. There are three flows in which stepper control have one form and second stepper control have 2 input fields.
When i have entered the firstStepperCtrl and navigate to second stepper and click on prev and come to second stepper which shows the validation.
Without touching the form , the validation is showing , how to reset the stepper and validate the stepper if second form field has been touched.
Here is the mark up:
<md-horizontal-stepper [linear]="isLinear" #stepper>
<md-step [stepControl]="firstFormGroup">
<form [formGroup]="firstFormGroup">
<ng-template mdStepLabel>Fill out your name</ng-template>
<md-form-field>
<input mdInput placeholder="Last name, First name" formControlName="firstCtrl" required>
</md-form-field>
<div>
<button md-button mdStepperNext>Next</button>
</div>
</form>
</md-step>
<md-step [stepControl]="secondFormGroup">
<form [formGroup]="secondFormGroup" #formDirective="ngForm">
<ng-template mdStepLabel>Fill out your address</ng-template>
<md-form-field>
<input mdInput placeholder="Address" formControlName="secondCtrl" required>
</md-form-field>
<md-form-field>
<input mdInput placeholder="phoneNo" formControlName="secondCtrlPhoneNo" required>
</md-form-field>
<div>
<button md-button mdStepperPrevious>Back</button>
<button md-button mdStepperNext>Next</button>
<button md-button (click)="resetWholeStepper(stepper)">Reset</button>
<button md-button (click)="reset2Stepper()">Reset1</button>
</div>
</form>
</md-step>
<md-step>
<ng-template mdStepLabel>Done</ng-template>
You are now done.
<div>
<button md-button mdStepperPrevious>Back</button>
<button md-button (click)="resetStepper(stepper)">Reset</button>
</div>
</md-step>
</md-horizontal-stepper>
app.component.ts
export class AppComponent implements OnInit, AfterViewInit {
private ngVersion: string = VERSION.full;
isLinear = false;
firstFormGroup: FormGroup;
secondFormGroup: FormGroup;
constructor(private _formBuilder: FormBuilder,) { }
// Event fired when component initializes
ngOnInit() {
this.firstFormGroup = this._formBuilder.group({
firstCtrl: ['', Validators.required]
});
this.secondFormGroup = this._formBuilder.group({
secondCtrl: ['', Validators.required],
secondCtrlPhoneNo:['',Validators.required]
});
}
// Event fired after view is initialized
ngAfterViewInit() {
}
resetWholeStepper(stepper: MdStepper){
stepper.selectedIndex = 0;
}
reset2Stepper1(formDirective: FormGroupDirective){
alert(2);
formDirective.resetForm();
// this.secondFormGroup.clearValidators();
this.secondFormGroup.reset();
}
[screencast link of issue]]1
demo

ngSubmit not working

I have an angular 4 form where I am trying to submit data
HTML Code
<form class="form-horizontal" [formGroup]="signupForm"
(ngSubmit)="onFormSubmit()" >
<fieldset>
<legend>Scheduler</legend>
<!--- Gender Block -->
<div class="form-group">
<label for="scheduleJob">Schedule Job</label>
<input type="text" formControlName = "schedulejob"
id="scheduleJob"
placeholder="Schedule Job">
Button code
<div class="form-group">
<button type="reset" class="btn btn-default">Cancel</button>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
Scheduler.TS file
import { Component, OnInit } from '#angular/core';
import { Scheduler } from 'rxjs/Scheduler';
/* Import FormControl first */
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
#Component({
selector: 'app-scheduler',
templateUrl: './scheduler.component.html',
styleUrls: ['./scheduler.component.css']
})
export class SchedulerComponent implements OnInit {
//Gender list for the select control element
private scheduleTypeList: string[];
//Property for the user
private scheduler:Scheduler;
private signupForm: FormGroup;
constructor(private fb:FormBuilder) { }
ngOnInit() {
this.scheduleTypeList = ['Type 1', 'Type 2', 'Type 3'];
this.signupForm = this.fb.group({
schedulejob: ['', Validators.required] ,
frequency: ['', Validators.required],
days: ['', Validators.required],
zone: ['', Validators.required],
schedulerjobtype:['', Validators.required]
})
}
public onFormSubmit() {
this.scheduler = this.signupForm.value;
if(this.signupForm.valid) {
this.scheduler = this.signupForm.value;
console.log(this.scheduler);
// alert(this.scheduler);
/* Any API call logic via services goes here */
}
//alert(this.scheduler);
console.log(this.scheduler);
}
}
Why is the execution not passed to onFormSubmit on submit click and alert or console.log not printing values?
Like I said in the comment, if your button is not inside your form it will not submit it.
So change to:
<form>
...
<button type="submit">Submit</button>
</form>
It is possible however to have it outside if you do it a bit differently, as described in this question.
I was having the same issue because I was not using a <form> tag to wrap my form.
a small trick you can do is to place an auxiliary hidden button inside the form and let the main button programmatically click the auxiliary button:
<form [formGroup]="form" (ngSubmit)="submit()">
...
<button type="submit" hidden #btn></button>
</form>
...
<button (click)="btn.click()">Submit</button>
you need to put the button code inside the form like below
<form class="form-horizontal"
[formGroup]="signupForm"
(ngSubmit)="onFormSubmit()" >
<fieldset>
<legend>Scheduler</legend>
<!--- Gender Block -->
<div class="form-group">
<label for="scheduleJob">Schedule Job</label>
<input type="text" formControlName = "schedulejob"
id="scheduleJob"
placeholder="Schedule Job">
<!-- Button Code Here -->
<div class="form-group">
<button type="reset" class="btn btn-default">Cancel</button>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
<!-- Form ends here -->
</form>
You can also use the form attribute in the submit button. This attribute uses the form's id to refer to it:
<form id="formID">
...
<button type="submit" form="formID">Submit</button>
</form>

How to display message on pattern validation?

I added pattern attribute to template
<input class="form-control" type="text" id="elementName"
[(ngModel)]="elementName" name="elementName"
(input)="onElementNameChanged()" #name="ngModel" required pattern="[A-Za-z0-9_)*\S]*" >
How to add message to display if input is not correct?
Something like wont work:
<div [hidden]="!name.errors.pattern"
class="alert alert-danger">
Name must match pattern
</div>
I strongly advise you to use ReactiveForms instead of TemplateDrivenForms as they are really good to manage validation patterns and messages.
An HTML snippet example :
<form novalidate [formGroup]="user" (ngSubmit)="onSubmit()">
<div formGroupName="account">
<md-input-container>
<input md-input type="text" placeholder="{{'USER.EMAIL' | translate}} *" formControlName="email" autocomplete="off">
<md-hint class="error" *ngIf="user.get('account.email').hasError('required') && user.get('account.email').touched">
{{'VALIDATOR.EMAIL_RQ' | translate}}
</md-hint>
<md-hint class="error" *ngIf="user.get('account.email').hasError('pattern') && user.get('account.email').touched">
{{'VALIDATOR.WRONG_EMAIL' | translate}}
</md-hint>
</md-input-container>
<md-input-container>
<input md-input type="password" placeholder="{{'USER.PASSWORD' | translate}} *" minlength="6" formControlName="password" autocomplete="off">
<md-hint class="error" *ngIf="user.get('account.password').hasError('required') && user.get('account.password').touched">
{{'VALIDATOR.PWD_RQ' | translate}}
</md-hint>
</md-input-container>
</div>
<button md-raised-button [disabled]="!user.valid || submitted" color="accent" type="submit" class="submit-button">
{{'LOGIN.BUTTON' | translate}}
</button>
</form>
This HTML example shows a login form with validation. Note how the md-hint elements show only when the form has the validation errors on the specific fields.
You can actually set an interface to match your ReactiveForm.
Here is the interface linked to the example :
export interface Account {
account: {
email: string;
password: string;
}
}
The TypeScript example snippet :
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
import { EmailRegex } from 'app/shared/shared.interface'; // Imported regex for validator
...
user: FormGroup;
ngOnInit() {
...
// Init your reactive form
this.user = this.formBuilder.group({
account: this.formBuilder.group({
email: ['', [Validators.required, Validators.pattern(EmailRegex)]],
password: ['', Validators.required]
})
});
}
Please note how the form groups match the interface. Also, you can set the form values there if you want to, but as you can see my fields email and password are set with an empty string value.
Note that you can also add as much validators as you want in the array linked to the field.
You can then access your form values on submit() directly from your primary FormGroup :
this.user.value.account.email
If this example wasn't good enough, I strongly suggest you read Todd Motto's guide on ReactiveForms which is really well explained :
https://toddmotto.com/angular-2-forms-reactive