I had the password input working perfectly until I added the verification. Now the input only becomes active when the password is toggled to visible.
Please advise. I am still learning.
import { Component, OnInit } from '@angular/core';
import { Validators, FormBuilder, FormGroup, FormControl } from '@angular/forms';
@Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
login: FormGroup;
showPassword: boolean;
showPin: boolean;
showConfirm: boolean;
// countries;
constructor(private fb: FormBuilder) {
this.login = this.fb.group({
password: new FormControl('', Validators.compose([
Validators.required,
Validators.minLength(8),
Validators.maxLength(20),
Validators.pattern('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&].{8,}$')
])),
email: new FormControl('', Validators.compose([
Validators.required,
Validators.minLength(6),
Validators.maxLength(20),
Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
])),
});
}
formSubmit(login) {
console.log('test: ', login);
}
togglePasswordText() {
this.showPassword = !this.showPassword;
}
toggleConfirmText() {
this.showConfirm = !this.showConfirm;
}
ngOnInit() {
}
}
And the html
<div class="color-top">
<div class="logo-top"><img src="assets/bb-logo-400.png" /></div>
</div>
<div class="spacer"></div>
<h4 class="ion-text-center">Welcome back</h4>
<!-- <p class="info-text ion-text-center ion-no-padding">Enter the 4 digit pin you received in your email</p> -->
<ion-list>
<form [formGroup]="login" (ngSubmit)="formSubmit(login)">
<!-- email -->
<ion-item>
<p *ngIf="login.controls.email.invalid && login.controls.email.dirty" class="alert-msg">
You need to enter a valid email
</p>
<ion-label position="floating">Email</ion-label>
<ion-input formControlName="email" name="email" type="email"></ion-input>
</ion-item>
<!-- password -->
<ion-item *ngIf="showPassword">
<p *ngIf="login.controls.password.invalid && login.controls.password.dirty" class="alert-msg">
Your password is incorrect. Please try again.
</p>
<ion-label position="floating">Password</ion-label>
<ion-input type="text" *ngIf="!showPasswordText" formControlName="password"></ion-input>
<ion-icon slot="end" color="primary" name="eye" (click)="togglePasswordText()"></ion-icon>
</ion-item>
<ion-item *ngIf="!showPassword">
<ion-label position="floating">Password</ion-label>
<ion-input type="password" *ngIf="!showPasswordText" formControlName="password"></ion-input>
<ion-icon slot="end" color="medium" name="eye-off" (click)="togglePasswordText()"></ion-icon>
</ion-item>
</form>
</ion-list>
<ion-button expand="full" shape="round" color="primary" type="submit" [disabled]="!login.valid">
Login</ion-button>
<div class="form-info-text ion-text-center">
<p><a>Reset password</a></p>
</div>
</ion-content>
type or paste code here
Write your code in this way it has same validators but call method is different , this wont create any issue with your visible and not visible password feature as well Just do remember to type password according to the validation. let me know if you have any doubt regarding the code.
I used ng-containers for better error message calls and put all my error messages in array and call themaccordingly.
In Html
<ion-content class="ion-padding">
<form class="form" [formGroup]="validations_form" (ngSubmit)="formSubmit(validations_form.value)">
<ion-item>
<ion-label position="floating" color="primary">Email</ion-label>
<ion-input type="text" formControlName="email"></ion-input>
</ion-item>
<div class="validation-errors">
<ng-container *ngFor="let validation of validation_messages.email">
<div class="error-message" *ngIf="validations_form.get('email').hasError(validation.type) && (validations_form.get('email').dirty || validations_form.get('email').touched)">
{{ validation.message }}
</div>
</ng-container>
</div>
<!-- Password -->
<ion-item *ngIf="showpassword">
<ion-label position="floating" color="primary">Password</ion-label>
<ion-icon slot="end" color="primary" name="eye" (click)="togglePasswordText()"></ion-icon>
<ion-input type="text" formControlName="password" class="form-controll" required></ion-input>
</ion-item>
<ion-item *ngIf="!showpassword">
<ion-label position="floating" color="primary">Password</ion-label>
<ion-input type="password" formControlName="password" class="form-controll" required></ion-input>
<ion-icon slot="end" color="medium" name="eye-off" (click)="togglePasswordText()"></ion-icon>
</ion-item>
<div class="validation-errors">
<ng-container *ngFor="let validation of validation_messages.password">
<div class="error-message" *ngIf="validations_form.get('password').hasError(validation.type) && (validations_form.get('password').dirty || validations_form.get('password').touched)">
{{ validation.message }}
</div>
</ng-container>
</div>
<ion-button class="submit-btn" type="submit" [disabled]="!validations_form.valid">Log In</ion-button>
<label class="error-message">{{errorMessage}}</label>
</form>
<ion-content>
Inside your .ts file
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
validations_form: FormGroup;
errorMessage: string = '';
loading: any;
public showpassword: boolean;
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.validations_form = this.formBuilder.group({
email: new FormControl('', Validators.compose([
Validators.required,
Validators.minLength(6),
Validators.maxLength(20),
Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$') // example : test@gmail.com
])),
password: new FormControl('', Validators.compose([
Validators.minLength(8),
Validators.maxLength(20),
Validators.required,
Validators.pattern('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&].{8,}$')
//example:- Test@123 (it will take one capital letter, one special char , one numeric digit then only it will allow to submit)
])),
});
}
togglePasswordText() {
this.showpassword = !this.showpassword;
}
validation_messages = {
'email': [
{ type: 'required', message: 'Email is required.' },
{ type: 'pattern', message: 'Please enter a valid email.' }
],
'password': [
{ type: 'required', message: 'Password is required.' },
{ type: 'minlength', message: 'Password must be at least 8 characters long. with one capital letter, one special char , one numeric digit ' }
]
};
Thank you very much. I will implement this.
Your welcome, Happy to help
if u feel this solved your problem do mark it as solution.
Thanks
Unfortunately this is not working either.
what is the error it is showing ? with the code i gave , because i tried the code on my end and it works as intended. i have made a stackblitz for the above code working with validation. also dont forget to add ReactiveFormsModule
in ur loginpage module
in the stackblitcz code i didnt put the showpassword function on ion-icon idk why but stackblitz wont recognize ion-icon so i made a button to use that function
Your code was perfectly fine. The problem was with the password swapping. It was undefined. Below is the fix to that problem. The ng-container was something i did not know about so I learnt something valuable. Thank you for your help.
export class LoginPage implements OnInit {
login: FormGroup;
showPassword = false;
errorMessage = '';
loading: any;
1 Like
awesome, glad i could help . do mark the a accepted answer for anyone coming here in future. Cheers 
Here is the working code. I did not make use of everything. This is working. The password validation will be on submit as this is a login, not registration.
html
<ion-content>
<div class="color-top">
<div class="logo-top"><img src="assets/bb-logo-400.png" /></div>
</div>
<div class="spacer"></div>
<h4 class="ion-text-center">Welcome back</h4>
<ion-list>
<form class="form" [formGroup]="login" (ngSubmit)="formSubmit(login.value)">
<ion-item>
<ng-container>
<p *ngIf="login.controls.email.invalid && login.controls.email.dirty" class="alert-msg">
You need to enter a valid email
</p>
</ng-container>
<ion-label position="floating" color="primary">Email</ion-label>
<ion-input type="text" formControlName="email"></ion-input>
</ion-item>
<!-- Password -->
<ion-item *ngIf="showPassword">
<ion-label position="floating" color="primary">Password</ion-label>
<ion-icon slot="end" color="primary" name="eye" (click)="togglePasswordText()"></ion-icon>
<ion-input type="text" formControlName="password" required></ion-input>
</ion-item>
<ion-item *ngIf="!showPassword">
<ion-label position="floating" color="primary">Password</ion-label>
<ion-input type="password" formControlName="password" required></ion-input>
<ion-icon slot="end" color="medium" name="eye-off" (click)="togglePasswordText()"></ion-icon>
</ion-item>
<ion-button style="margin-top:30px;" expand="full" shape="round" color="primary" type="submit" [disabled]="!login.valid">Log In</ion-button>
</form>
</ion-list>
<ion-content>
The typescript
import { Component, OnInit } from '@angular/core';
import { Validators, FormBuilder, FormGroup, FormControl } from '@angular/forms';
@Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
login: FormGroup;
showPassword = false;
errorMessage = '';
loading: any;
// countries;
constructor(private fb: FormBuilder) {
this.login = this.fb.group({
email: new FormControl('', Validators.compose([
Validators.required,
Validators.minLength(6),
Validators.maxLength(20),
Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
])),
password: new FormControl('', Validators.compose([
Validators.required,
Validators.minLength(8),
// Validators.maxLength(20),
// Validators.pattern('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&].{8,}$')
])),
});
}
ngOnInit() {
}
formSubmit(login) {
console.log('test: ', login);
}
togglePasswordText() {
console.log('togglePasswordText: ', this.showPassword);
this.showPassword = !this.showPassword;
}
}
Sass
ion-header {
--border-width: 0 0 0;
ion-toolbar {
--border-width: 0 0 0;
overflow: visible;
h2 {
font-size: 1rem;
}
}
}
ion-content {
.color-top {
position: relative;
display: block;
width: 100%;
height: 25vh;
background: var(--ion-color-primary);
.logo-top {
position: absolute;
z-index: 1000;
left: 50%;
transform: translate(-50%, 25%);
img {
width: 40vw;
}
}
}
.spacer {
display: block;
height: 8vh;
}
h4 {
color: var(--ion-color-primary);
padding-top: 8px;
}
.info-text {
margin-top: 0;
margin-bottom: 20px !important;
}
ion-list {
margin-bottom: 20px;
.form-title {
text-align: left;
color: var(--ion-color-primary);
font-weight: 600;
font-size: 1rem;
margin-left: 16px;
margin-bottom: 0;
margin-top: 30px;
.form-title-note {
font-size: 0.9rem;
font-style: italic;
font-weight: normal;
color: var(--ion-color-dark)
}
}
ion-item-divider {
ion-label {
text-transform: uppercase;
}
}
ion-item {
--border-color: var(--ion-inactive-on-red);
ion-label {
margin-left: 0px;
text-transform: uppercase;
color: var(--ion-color-primary);
font-size: 0.8rem;
}
ion-input {
--font-size: 1rem;
--color: var(--ion-color-dark);
margin-bottom: 10px;
}
ion-row {
margin-top: 20px;
padding-bottom: 5px;
ion-input {
--placeholder-color: var(--ion-color-primary);
--placeholder-opacity: 0.4;
}
}
ion-icon {
font-size: 2rem;
margin-top: 27px;
}
}
}
ion-button {
margin-left: 20vw;
margin-right: 20vw;
}
}
// Form error message
.alert-msg {
position: absolute;
left: 0;
right: 0;
width: 100%;
font-size: 0.8rem;
text-align: center;
color: var(--ion-color-primary-shade);
font-weight: 400;
padding: 10px;
margin-left: auto;
margin-top: 50px;
margin-right: auto;
border-radius: 5px;
padding-top: 3px;
padding-bottom: 0;
margin-bottom: 0;
height: 17px;
}
1 Like