How to validate multiple preselected checkbox with angular 8 reactive form - html

I have few checkboxes whose values are coming from loop,Here I am validating those checkboxes using reactive form.My validation is atleast one checkboxes should be selected.when I check and uncheck the checkbox validation is working fine,but when my all checkboxes are already preselected and click submit,even though its showing empty message.Is there any solution for it.Here is the code below.
home.component.html
<div>
<p>Form 1</p>
<form [formGroup]="registerForm">
<div *ngFor="let grpdata of statusdata">
<input type="checkbox" formControlName="title" value="{{grpdata.groupid}}" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.title.errors }">{{grpdata.groupname}}<br>
</div>
<div *ngIf="submitted && f.title.errors" class="invalid-feedback">
<div *ngIf="f.title.errors.required">Title is required</div>
</div>
<button type="submit" (click)="getSelectedVal()">Click here</button>
</form>
</div>
<div>
<p>Form 2</p>
<form [formGroup]="editForm">
<input type="textbox" disabled formControlName="edithidden" [(ngModel)]="hello" class="form-control"><br>
<div *ngFor="let grpdata of statusdata">
<input type="checkbox" formControlName="edittitle" [checked]=true value="{{grpdata.groupid}}" class="form-control" [ngClass]="{ 'is-invalid': submitted1 && g.edittitle.errors }">{{grpdata.groupname}}<br>
</div>
<div *ngIf="submitted1 && g.edittitle.errors" class="invalid-feedback">
<div *ngIf="g.edittitle.errors.required">Title is required</div>
</div>
<button type="submit" (click)="editSelectedVal()">Click here</button>
</form>
</div>
home.component.ts
import { Component, OnInit } from '#angular/core';
import { CommonserviceService } from './../utilities/services/commonservice.service';
import { FormBuilder, FormControl, FormGroup, Validators } from '#angular/forms';
declare var $: any;
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
submitted = false;
submitted1 = false;
getListData: any;
registerForm: FormGroup;
editForm: FormGroup;
statusdata: any;
constructor(private commonserviceService: CommonserviceService,private formBuilder: FormBuilder)
{
this.registerForm = this.formBuilder.group({
title: [false, Validators.requiredTrue],
});
this.editForm = this.formBuilder.group({
edittitle: [false, Validators.requiredTrue],
edithidden: new FormControl()
});
}
ngOnInit() {
this.statusdata = [{"groupid":1,"groupname":"project1"},{"groupid":2,"groupname":"project2"},{"groupid":3,"groupname":"project3"}];
}
get f() { return this.registerForm.controls; }
get g() { return this.editForm.controls; }
getSelectedVal(){
this.submitted = true;
// stop here if form is invalid
if (this.registerForm.invalid) {
return;
}
console.log('submitted');
}
editSelectedVal(){
this.submitted1 = true;
// stop here if form is invalid
if (this.editForm.invalid) {
return;
}
console.log('submitted edit');
}
}

<input type="checkbox" formControlName="edittitle" [checked]=true...
You shouldn't try to set the value from outside of the form. You never know when it is actually attached. When you want to have the checkbox to be preselected use the form value instead.
this.editForm = this.formBuilder.group({
edittitle: [true, Validators.requiredTrue], // true here, you had false here
edithidden: new FormControl()
});

Related

Angular FormArray

I m not able to access the FormArray in Angular 13.3. its showing this error in console. I have one form group, inside that I have 2 more form groups and 1 form array.
core.mjs:6485 ERROR Error: Cannot find control with name: 'third'
Here is my HTML code:
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<div [formGroup]="bankFormGroup">
<input type="text" placeholder="property11" formControlName="property11">
<div *ngIf="bankFormGroup.get('property11')?.invalid && (bankFormGroup.get('property11')?.dirty || bankFormGroup.get('property11')?.touched)" class="alert">
<div *ngIf="bankFormGroup.get('property11')?.errors?.['required']">
Required.
</div>
</div>
<div [formGroup]="bankForm2Group">
<input type="text" placeholder="property21" formControlName="property21">
<div *ngIf="bankForm2Group.get('property21')?.invalid && (bankForm2Group.get('property21')?.dirty || bankForm2Group.get('property21')?.touched)" class="alert">
<div *ngIf="bankForm2Group.get('property21')?.errors?.['required']">
Required.
</div>
</div>
</div>
<ul class="list-group">
<li class="list-group-item" formArrayName="third" *ngFor="let product of bankForm3Group.controls; let i = index;">
<div [formGroupName]="i" class="row">
<div class="col-4">
<input type="text" formControlName="property3" class="form-control" id="property3" placeholder="property3">
</div>
</div>
</li>
</ul>
</div>
<div [formGroup]="bankFormGroup">
<input type="text" placeholder="property12" formControlName="property12">
</div>
<button type="submit">Submit</button>
</form>
TS code:
declare var $: any;
import { Component, OnInit } from '#angular/core';
import { FormArray, FormControl, FormGroup, Validators } from '#angular/forms';
#Component({
selector: 'app-first',
templateUrl: './first.component.html',
styleUrls: ['./first.component.css']
})
export class FirstComponent implements OnInit {
form!: FormGroup;
constructor() {
this.form = new FormGroup({
first: new FormGroup({
property11: new FormControl('property 1.1', Validators.required),
property12: new FormControl('property 1.2', Validators.required)
}),
second: new FormGroup({
property21: new FormControl('property 2.1', Validators.required)
}),
third: new FormArray([
new FormGroup({
property3: new FormControl('property 3')
}),
new FormGroup({
property3: new FormControl('property 3')
}),
])
});
}
get bankFormGroup(): FormGroup {
return this.form?.get('first') as FormGroup;
}
get bankForm2Group(): FormGroup {
return this.form?.get('second') as FormGroup;
}
get bankForm3Group(): FormArray {
return this.form?.get('third') as FormArray;
}
//get third(): FormArray {
// return this.form?.get('third') as FormArray;
//}
onSubmit() {
console.log('Submit', this.form.value);
}
ngOnInit(): void {
$(".preloader").hide();
}
}
I have separate FormGroup in TS but in HTML its nested. I create Getter Methods which resolved almost. but I m not able to access FormArray by this. I spent lot of time but no luck. Thanks in advance.
The main problem is that your "divs" are closed wrong. In this stackblitz I ordered the div of your .html.
NOTE 1: You can use formGroupName="first" and formGroupName="second" instead of [formGroup]="bankFormGroup" and [formGroup]="backForm2Group"
NOTE2: You can use the way form.get('formgroupname.formControlName') in your *ngIf,e.g.
<div *ngIf="form.get('second.property21')?.invalid>...</div>
NOTE3:I like more that the formArrayName="third" was in the <ul> instead of the <li> with the *ngFor (but it is a personal opinion)
NOTE4: For me is strange in the .html that you show the inputs "property 1.1" (from the formGroup "first") and "property 1.2" (from the formGroup "second"), and the last input the input "property 1.2" (from the formGroup "first")
Thank you #Eliseo, I have achieved my requirement. I have used <ng-container> to segregate the form group and their elements. By this approach I no longer needed getter methods too. Here is my updated code
HTML:
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<!--classess removed for clarity-->
<!--parent div contains first and second group. ng container has been used for each group-->
<div>
<!--accessing first group-->
<ng-container formGroupName="first">
<input type="text" placeholder="property11" formControlName="property11">
<div *ngIf="form.get('first.property11')?.invalid && (form.get('first.property11')?.dirty || form.get('first.property11')?.touched)" class="alert">
<div *ngIf="form.get('first.property11')?.errors?.['required']">
Required.
</div>
</div>
</ng-container>
<!--classess removed for clarity-->
<div>
<!--accessing second group-->
<ng-container formGroupName="second">
<input type="text" placeholder="property21" formControlName="property21">
<div *ngIf="form.get('second.property21')?.invalid && (form.get('second.property21')?.dirty || form.get('second.property21')?.touched)" class="alert">
<div *ngIf="form.get('second.property21')?.errors?.['required']">
Required.
</div>
</div>
</ng-container>
</div>
<ul>
<!--accessing third array-->
<ng-container formArrayName="third">
<li *ngFor="let product of third.controls; let i = index;">
<div [formGroupName]="i">
<div>
<input type="text" formControlName="property3" id="property3" placeholder="property3">
</div>
</div>
</li>
</ng-container>
</ul>
</div>
<!--classess removed for clarity-->
<div>
<!--accessing first group back again-->
<ng-container formGroupName="first">
<input type="text" placeholder="property12" formControlName="property12">
</ng-container>
</div>
<button type="submit">Submit</button>
</form>
TS Code:
declare var $: any;
import { Component, OnInit } from '#angular/core';
import { FormArray, FormControl, FormGroup, Validators } from '#angular/forms';
#Component({
selector: 'app-first',
templateUrl: './first.component.html',
styleUrls: ['./first.component.css']
})
export class FirstComponent implements OnInit {
form!: FormGroup;
constructor() {
this.form = new FormGroup({
first: new FormGroup({
property11: new FormControl('property 1.1', Validators.required),
property12: new FormControl('property 1.2', Validators.required)
}),
second: new FormGroup({
property21: new FormControl('property 2.1', Validators.required)
}),
third: new FormArray([
new FormGroup({
property3: new FormControl('property 3')
}),
new FormGroup({
property3: new FormControl('property 3')
}),
])
});
}
get third(): FormArray {
return this.form?.get('third') as FormArray;
}
onSubmit() {
console.log('Submit', this.form.value);
}
ngOnInit(): void {
$(".preloader").hide();
}
}
If there is any room of improvement then please let me know. I will update the code.

ReactiveForms refresh page after submitting in Angular CLI

I am following the tutorial:
https://jasonwatmore.com/post/2018/10/29/angular-7-user-registration-and-login-example-tutorial
and write a login form according to this by using ReactiveFormsModule in Angular 7
However, after I click on submit with wrong information I just see alert at top for a second and page refreshes itself. I searched a lot about this topic and changing button type does not help.
Here is my HTML code:
<div>
<h2 align="center">Login</h2>
<form [formGroup]="loginForm">
<div class="form-group">
<label for="email">E-mail</label>
<input type="text" formControlName="email" class="form-control" placeholder="your_email#example.com" [ngClass]="{ 'is-invalid': submitted && f.email.errors }" />
<div *ngIf="submitted && f.email.errors" class="invalid-feedback">
<div *ngIf="f.email.errors">Invalid e-mail</div>
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" formControlName="password" placeholder="******" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.password.errors }" />
<div *ngIf="submitted && f.password.errors" class="invalid-feedback">
<div *ngIf="f.password.errors" >Invalid password</div>
</div>
</div>
<div class="form-group">
<button (click)="onSubmit()" [disabled]="loading || !loginForm.controls.email.value || !loginForm.controls.password.value" class="btn btn-primary">Login</button>
<img *ngIf="loading" class="pl-2" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
</div>
<a routerLink="/register" class="go-register">Do you need an account?</a>
</form>
</div>
and TypeScript file:
import { Component, OnInit , OnDestroy} from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { FormBuilder, FormGroup, Validators} from '#angular/forms';
import { first } from 'rxjs/operators';
import { AuthenticationService } from '../services/auth.service';
import { AlertService } from '../services/alert.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
loading = false;
submitted = false;
returnUrl: string;
error = '';
constructor(
private formBuilder: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private authenticationService: AuthenticationService,
private alertService: AlertService
) { }
ngOnInit() {
this.loginForm = this.formBuilder.group({
email: ['', [Validators.email, Validators.required]],
password: ['', [Validators.pattern('^(?=[^A-Z]*[A-Z])(?=[^a-z]*[a-z])(?=[^0-9]*[0-9]).{6,}$'),
Validators.minLength(6),
Validators.required]]
});
// reset login status
this.authenticationService.logout();
// get return url from route parameters or default to '/'
this.returnUrl = this.route.snapshot.queryParams.returnUrl || '/';
}
// convenience getter for easy access to form fields
get f() { return this.loginForm.controls; }
onSubmit() {
this.submitted = true;
// stop here if form is invalid
if (this.loginForm.invalid) {
return;
}
this.loading = true;
this.authenticationService.login(this.f.email.value, this.f.password.value)
.subscribe(
data => {
this.router.navigate([this.returnUrl]);
},
error => {
this.error = error;
// alert(error);
this.alertService.error(error);
this.loading = false;
});
}
}
I debug my code and I guess problem is about HTML but I cannot resolve.
Also, I tried add event.preventDefault() and (ngSubmit), none of them helped me.
I am open for any ideas...
https://angular.io/guide/reactive-forms#saving-form-data
You have to use ngSubmit...
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
Then the default behaviour is disabled and angular handles it.

how to specify the value of our checkbox

I want that when the user checks on checkbox, the value be "l.code" instead of a Boolean value
Here's my code
<div class="form-group">
<label>Critères : </label>
<div class="checkbox-inline" *ngFor="let l of lesCriteres; let i= index">
<label>
<input type="checkbox" [value]="l.code" [(ngModel)]="actif.lesCriteresActifs[i].critere.code">{{l.code}}
</label>
</div>
</div>
But it does not work ! when I check, it gives me "true" instead of "l.code". Thanks !
You can use "change" event handler with event binding on checkbox.
In html
<form>
<div *ngFor="let l of lesCriteres">
<input type="checkbox" value="l.code" (change)="onChangeEvent($event, l.code)"> {{l.code}}<br>
</div>
</form>
In ts
onChangeEvent(eventValue, valueOfCheckbox){
alert(valueOfCheckbox);
}
You can do something like below :
HTML:
<div *ngFor="let data of emails">
<input type="checkbox" [value]="data.email" (change)="onChange(data.email, $event.target.checked)"> {{data.email}}<br>
</div>
ts:
import { Component } from '#angular/core';
import { FormGroup, FormBuilder, FormArray, FormControl } from '#angular/forms';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular 6';
emailFormArray = [];
emails = [{ email: "email1" }, { email: "email2" }, { email: "email3" }, { email: 'email4' }]
myForm: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.myForm = this.fb.group({
useremail: this.fb.array([])
});
}
onChange(email: string, isChecked: boolean) {
if (isChecked) {
this.emailFormArray.push(email);
} else {
let index = this.emailFormArray.findIndex(x =>{
console.log(x);
return x == email
});
console.log(index)
this.emailFormArray.splice(index,1);
}
console.log(this.emailFormArray)
}
}
STACKBLITZ

My CRUD Application In Angular Using API is not working as a Single Page Application(SPA) while updating

I have performed the CRUD Application In Angular Using API and it is working fine but the problem is that when I am updating the values it is not showing the updated value instantly, I have to reload the page.
This is my app.component.ts:
import {Component} from '#angular/core';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import {Employee} from './employees';
import {EditComponent} from './edit/edit.component';
import {AppService} from './app.service';
import {Router} from '#angular/router';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [AppService]
})
export class AppComponent {
form:any = {}
msg: string = null;
employees: Employee[];
constructor(
public http: HttpClient,private appService:AppService,private router: Router
){}
onSubmit(){
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
this.http.post('http://127.0.0.1:8000/api/employee',this.form,httpOptions)
.subscribe(employee=>{
employee = employee;
this.msg = 'Updated successfully!';
this.getEmployee();
});
}
ngOnInit() {
this.getEmployee();
}
getEmployee():void{
this.appService.getEmployees().subscribe(employees=>(this.employees = employees))
}
delete(employee: Employee): void{
if(confirm("Are you sure want to delete ?")) {
console.log("user details delete successfully!!");
this.employees = this.employees.filter(h =>h !== employee);
this.appService.deleteEmployees(employee.id).subscribe();
this.msg = 'Employee details delete successfully!!';
}else{
}
}
public editComponent: boolean = false;
loadMyChildComponent($id)
{
this.editComponent = true;
this.appService.setCurrentId($id);
}
}
This is my edit.component.ts:
import {Component, OnInit, Input} from '#angular/core';
import {AppService} from '../app.service';
import {Employee} from '../employees';
import {Router} from '#angular/router';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import {NgForm} from '#angular/forms';
import {Observable} from 'rxjs';
import { ActivatedRoute } from '#angular/router';
import {FormBuilder, FormGroup, Validators} from "#angular/forms";
#Component({
selector: 'app-edit',
templateUrl: './edit.component.html',
styleUrls: ['./edit.component.css']
})
export class EditComponent implements OnInit {
#Input() employee: Employee[];
form:any = {}
msg: string = null;
constructor(public http: HttpClient,private appService:AppService,private router: Router,private route: ActivatedRoute) { }
ngOnInit(){
this.editEmployees();
}
editEmployees():void{
const id = this.appService.getCurrentId();
this.appService.editEmployees(id).subscribe(employee => {
this.employee = employee;
this.editEmployees();
});
}
onformSubmit()
{
this.appService.updateEmployees(this.employee).subscribe(employee=>{
this.employee = employee;
this.msg = 'Updated successfully!';
});
}
}
This is my employees.ts:
export interface Employee{
id: number;
username:string;
email:string;
mobile:string;
password:string;
}
This is my app.component.html: where I am showing the values and edit button.
<table class="table">
<tr>
<th>Id</th>
<th>User Name</th>
<th>Email</th>
<th>Mobile</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<tr *ngFor="let employee of employees">
<td>{{employee.id}}</td>
<td>{{employee.username}}</td>
<td>{{employee.email}}</td>
<td>{{employee.mobile}}</td>
<td><button (click)="loadMyChildComponent(employee.id);" class="btn btn-primary" [routerLink]="['/edit',employee.id]">Edit</button></td>
<td><button class="btn btn-danger" (click)="delete(employee)" > Delete</button></td>
</table>
This is my edit.component.html:
<div class="mydiv22">
<p class="msg_success">{{ msg }}</p>
<h2>Update Form</h2>
<div class="row">
<div class="col-md-12">
<form name="form" (ngSubmit)="f.form.valid && onformSubmit()" #f="ngForm" novalidate>
<div class="form-group">
<label for="username">User Name</label>
<input type="text" class="form-control" name="username" [(ngModel)]="this.employee.username" #username="ngModel"
[ngClass]="{'is-invalid': f.submitted && username.invalid}" required id="username"/>
<div *ngIf="f.submitted && username.invalid" class="invalid-feedback">
<div *ngIf="username.errors.required">>> required</div>
</div>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" name="email" [(ngModel)]="this.employee.email" #email="ngModel" [ngClass]="{'is-invalid': f.submitted && email.invalid}"
required email placeholder="Enter your email address" id="email"/>
<div *ngIf="f.submitted && email.invalid" class="invalid-feedback">
<div *ngIf="email.errors.required">>> required</div>
<div *ngIf="email.errors.email">>> must be a valid email address</div>
</div>
</div>
<div class="form-group">
<label for="mobile">Mobile</label>
<input type="number" class="form-control" name="mobile" [(ngModel)]="this.employee.mobile" #mobile="ngModel"
[ngClass]="{'is-invalid': f.submitted && mobile.invalid}" required placeholder="Enter your mobile" pattern="[789][0-9]{9}" minlength="10" id="mobile"/>
<div *ngIf="f.submitted && mobile.invalid" class="invalid-feedback">
<div *ngIf="mobile.errors.required">>> required</div>
<div *ngIf="mobile.errors.pattern">>>Please enter a valid mobile number</div>
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password" [(ngModel)]="this.employee.password" #password="ngModel"
[ngClass]="{'is-invalid':f.submitted && password.invalid}" required minlength="6" placeholder="Create your password" id="password"/>
<div *ngIf="f.submitted && password.invalid" class="invalid-feedback">
<div *ngIf="password.errors.required">>> required</div>
<div *ngIf="password.errors.minlength">>> must be at least 6 characters</div>
</div>
</div>
<div class="form-group">
<button routerLink="/edit" class="btn btn-success">Update</button>
</div>
</form>
</div>
</div>
</div>
The flow is that: when i click the edit button in app.component.html, It will take the id and go to app.component.ts. From app.component.ts, it will go to app.service.ts where it will fetch the values from the API using particular Id. From the app.service.ts, it will pass the values to the edit.component.ts and using edit.component.ts, it will pass the values to edit.component.html.
It is performing every thing fine like when adding the value it is showing instantly, I don't have to reload the page but while updating the values we have to reload the page, it is not showing instantly like SPA.
I want to show the updated values instantly without updating the page. Any help is much appreciated.
You have three components in same page, it is something about component interactions.
Add Output event property in to EditComponent, emit an event after editing of employee , like this:
import { Output, EventEmitter } from '#angular/core'
export class EditComponent {
#Output() updated = new EventEmitter<Employee>();
onFormSubmit() {
this.appService.updateEmployees(this.employee).subscribe(employee=>{
this.employee = employee;
this.msg = 'Updated successfully!';
// fire an updated event after edit employee.
this.updated.emit(employee)
});
}
}
Then, subscribe to the event in app.component.html, like this:
<app-edit (updated)="onUpdated()"></app-edit>
And then, call getEmployee in onUpdated method to reload the employees list , like this:
export class AppComponent {
onUpdated() {
this.getEmployee();
}
}
For more, please refer to https://angular.io/guide/component-interaction
You can add the similar logic to RegisterComponent to get a reload.

Angular 4 validation is showing when the page load's

i'm working on angular 4 form and set some validations on the input field but the validation is show when the page load's but i want the validation when the form is submitted or the email pattern is not valid.
<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm.value)"
[class.error]="!myForm.valid && myForm.touched">
<div class="field" [class.error]="!email.valid && email.touched">
<label for="email">Email</label>
<input type="email" id="email" name="email" [formControl]="email">
<div *ngIf="!email.valid"
class="ui error message">Email is invalid</div>
<div *ngIf="email.hasError('required')"
class="ui error message">Email is required</div>
</div>
<div *ngIf="!myForm.valid"
class="ui error message">Form is invalid</div>
<button type="submit">login</button>
</form>
Typescript code:
function EmailValidator(control: FormControl): { [s: string]: boolean } {
if (!control.value.match('^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$'))
{
return {invalidEmail: true};
}
}
#Component({
selector: 'app-login-form',
templateUrl: './login-form.component.html',
styleUrls: ['./login-form.component.css']
})
export class LoginFormComponent implements OnInit {
myForm: FormGroup;
email: AbstractControl;
constructor(fb:FormBuilder) {
this.myForm = fb.group({
'Email': ['', Validators.compose([
Validators.required, EmailValidator])
]
});
this.email = this.myForm.controls['Email'];
}
onSubmit(form: string): void {
console.log('you submitted value:', form);
}
}
you can use
<div
*ngIf="myForm.get('email').hasErrors('required') &&
myForm.get('email').touched">
Email is required
</div>
And adapt hasError to your validation