Angular Material Hide Password toggles on enter - html

I'm new to angular and i have a project that already has a login with a username and password input. The password input has a button to show the password. The problem is, that when im in the password input field and i press enter, it toggles the button to show the password instead of submitting the form. How can i change that?
component.html
<div style="text-align: center" class="centered">
<form [formGroup]="form">
<br>
<mat-form-field appearance="fill">
<mat-label>Username</mat-label>
<input name="username" formControlName="username" matInput>
</mat-form-field>
<br>
<mat-form-field appearance="fill">
<mat-label>Password</mat-label>
<input name="password" formControlName="password" matInput [type]="passwordVisible ? 'text' : 'password'">
<button mat-icon-button matSuffix (click)="passwordVisible = !passwordVisible" [attr.aria-label]="'Hide password'"
[attr.aria-pressed]="!passwordVisible">
<mat-icon>{{passwordVisible ? 'visibility' : 'visibility_off'}}</mat-icon>
</button>
</mat-form-field>
<br>
<button (click)="login()" mat-raised-button>Login</button>
<button (click)="navigateToRegister()" mat-raised-button color="primary" style="margin-left: 10px">Register</button>
</form>
</div>

Default type for the button is submit that might be causing this issue try changing your show/hide button type to button something like
<button type="button" mat-icon-button matSuffix (click)="passwordVisible = !passwordVisible" [attr.aria-label]="'Hide password'"
[attr.aria-pressed]="!passwordVisible">
<mat-icon>{{passwordVisible ? 'visibility' : 'visibility_off'}}</mat-icon>
</button>

I also stumbled upon this issue recently and was able to resolve it using the approach below.
Method onClickRevealPassword will be called if you press enter on the password input field. Such action results in an event called pointerType which you can detect with this method and keep the password field not to reveal the plain password value. Have a look and experiment it with your component.
<mat-form-field appearance="fill">
<mat-label>Password</mat-label>
<input name="password" formControlName="password" matInput [type]="passwordVisible ? 'text' : 'password'">
<button mat-icon-button matSuffix (click)="passwordVisible = !passwordVisible; onClickRevealPassword($event)" [attr.aria-label]="'Hide password'"
[attr.aria-pressed]="!passwordVisible">
<mat-icon>{{passwordVisible ? 'visibility' : 'visibility_off'}}</mat-icon>
</button>
</mat-form-field>
onClickRevealPassword(event) {
event.preventDefault();
// Prevent revealing the password when enter button is pressed.
if (event?.pointerType) {
this.passwordVisible = !this.passwordVisible;
}
}

Related

HTML & Angular Material disable save button from outside div when form fields are empty

I have the following Angular Material form with the Close and Save buttons in an outside div for design reasons:
<h1 mat-dialog-title>Product Page</h1>
<div mat-dialog-content>
<form [formGroup]="productForm">
<mat-form-field appearance="outline">
<mat-label>Name</mat-label>
<input formControlName="name" required matInput placeholder="Name" style="text-transform:uppercase">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Weight</mat-label>
<input type="number" required formControlName="weight" matInput placeholder="weight">
</mat-form-field>
</form>
</div>
<div mat-dialog-actions [align]="'end'">
<button mat-raised-button color="warn" mat-dialog-close>Close</button>
<button mat-raised-button color="primary" (click)="saveProduct()">Save</button>
</div>
I want to disable the Save button when the form fields are empty but the required parameter isn't working since the buttons are in an outside div. Is there a way to correlate the buttons with the form such that the Save button is disabled until the required fields are filled in?
You can bind it manually :
<button (click)="submit()" [disabled]="!form.valid">Submit</button>
Or you can cheat your way in the modal by providing the form as the main container (yes, it works)
<form [formGroup]="form">
<h1 mat-dialog-title>...</h1>
<div mat-dialog-content>...</div>
<div mat-dialog-actions align="end">
<button type="submit" [disabled]="!form.valid">Submit</button>
</div>
</form>
You could add a validation to your formGroup and use the formGroup to set the button disabled:
on your component:
constructor(fb:FormBuilder
(...)
) {
this.productForm = fb.group({
name: [null, Validators.required]
(...)
})
}
then on your template, adjust the button:
<button mat-raised-button color="primary" [disabled]="productForm.invalid" (click)="saveProduct()">Save</button>
You might as well remove the 'required' from you input (as angular will warn you about this in the console):
<input formControlName="name" matInput placeholder="Name" style="text-transform:uppercase">

mat-icon-button matSuffix in field password always refresh when click

I want to ask about mat-icon-button matSuffix in angular
actually this is my first time I learning angular and try to create a login page,
and I got some problem in password field
I used mat-icon-button matSuffix, every time I click on icon hide or show password the page always refresh and all fields back to empty again
here is my code
<div class="form-field">
<mat-form-field class="field-full-width" appearance="fill">
<mat-label>Enter your password</mat-label>
<input matInput [type]="hide ? 'password' : 'text'" />
<button
mat-icon-button
matSuffix
(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>
I copied from angular website. The code running well it that site, but not in my code
this my angular version
The issue is that a button tag's default behavior is to perform a form submit...
You should add type="button" and it will stop refreshing.
<button
type="button"
mat-icon-button
...

input onfocus event not detecting html element when reference them by #

Todo :
I want to open a date picker "#picker" when its input has focus but it's not working when using onfocus input event and gives an error:
error : 'picker is not defined'
<mat-form-field style="width: 100%;">
<input matInput [matDatepicker]="picker" onfocus="picker.open()"
placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker">
</mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
but when I did it by a button press it worked
<button mat-button (click)="picker.open()">show date picker</button>
how can I do this by focusing on an input
You should use Angular event binding:
<input ... (focus)="picker.open()" >
See this stackblitz for a demo.

Angular material button does not change color

Hey people I'm facing an issue where Angular material button's color does bot apply in some cases, just like this one:
html:
<mat-card>
<mat-spinner *ngIf="isLoading"></mat-spinner>
<form [formGroup]="form" (submit)="onLogin()" *ngIf="!isLoading">
<mat-form-field>
<input matInput type="email" formControlName="email" placeholder="Email">
<mat-error *ngIf="form.get('email').invalid">Please enter a valid email.</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput type="password" formControlName="password" placeholder="Password">
<mat-error *ngIf="form.get('password').invalid">Please enter a valid password.</mat-error>
</mat-form-field>
<mat-action-row>
<!-- NOT COLORED-->
<button mat-raised-button type="submit" color="warn">Login</button>
</mat-action-row>
</form>
<!-- COLORED-->
<button mat-raised-button type="submit" color="warn">Login</button>
</mat-card>
result:
As you can see, both buttons has same code, but for one the color is applied and for the other one it doesnt, and I want to use that color inside my form... any solutions?
I had a similar problem with the mat-select and mat-options components. I know this post is dated, but this is still a common problem. Sometimes when you add a style to a material component it just doesn't work.
For me, I managed to get it to work by moving my material related styles to the global stylesheet. This seems to work consistently.
problem solved by adding :
this.form = this.fb.group({
email: ['', [Validators.required]],
password: ['', [Validators.required]]
});
in the compponent.ts file

Angular Material Expansion panel click event

<mat-expansion-panel (opened)="panelOpenState = true" (closed)="panelOpenState = false" (click)="getPrimaryAddress()">
<mat-expansion-panel-header>
<mat-panel-title>
Primay Address
</mat-panel-title>
<mat-panel-description>
{{panelOpenState ? 'Hide' : 'Display'}} Address
</mat-panel-description>
</mat-expansion-panel-header>
<div>
<mat-form-field class="example-form-field" style="margin-top: 20px;">
<input matInput type="text" placeholder="Street 1" [(ngModel)]="streetOneValue">
<button mat-button *ngIf="streetOneValue " matSuffix mat-icon-button aria-label="Clear" (click)="streetOneValue=''">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
<mat-form-field class="example-form-field" style="margin-top: 20px;">
<input matInput type="text" placeholder="Street 2" [(ngModel)]="streetTwoValue">
<button mat-button *ngIf="streetTwoValue " matSuffix mat-icon-button aria-label="Clear" (click)="streetTwoValue=''">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
</div>
<div>
<mat-form-field class="example-form-field" style="margin-top: 20px;">
<input matInput type="text" placeholder="Street 3" [(ngModel)]="streetThreeValue">
<button mat-button *ngIf="streetThreeValue " matSuffix mat-icon-button aria-label="Clear" (click)="streetThreeValue=''">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
<mat-form-field class="example-form-field" style="margin-top: 20px;">
<input matInput type="text" placeholder="Street 2" [(ngModel)]="countyValue">
<button mat-button *ngIf="countyValue " matSuffix mat-icon-button aria-label="Clear" (click)="countyValue=''">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
</div>
<div>
<mat-form-field class="example-form-field" style="margin-top: 20px;">
<input matInput type="text" placeholder="Post Code" [(ngModel)]="postcodeValue">
<button mat-button *ngIf="postcodeValue " matSuffix mat-icon-button aria-label="Clear" (click)="postcodeValue=''">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
<mat-form-field class="example-form-field" style="margin-top: 20px;">
<input matInput type="text" placeholder="Country" [(ngModel)]="primaryAddresscountryValue">
<button mat-button *ngIf="primaryAddresscountryValue " matSuffix mat-icon-button aria-label="Clear" (click)="primaryAddresscountryValue=''">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
</div>
</mat-expansion-panel>
Just started playing around with Angular Material and have run into an issue with the mat-expansion-panel. My panel hosts a series of mat-form-field elements at appear when expanded.
I have several click events one that gets the data; (click)="getPrimaryAddress()
and the rest just clear the data once the X button is selected e.g (click)="streetOneValue=''"
However when I click the X button to clear a particular value the getPrimaryAddress() event fires again and just re-populates the data in the element. Is there anyway to stop the getPrimaryAddress() function from firing whenever I select the other click events?
I need the data to lazy load which is why I am handling it in a click event and not OnInit
You can do the loading in the opened event you are already using. Then you don't need to use the click event and it is also more correct. From what I understand you want to load the data when the panel expands. There is also another afterExpand event you can also use.
You get the click event on the panel when you press a button because the buttons are child elements of the panel and you handle the click also in the panel element so both receive the event. Also any mouse click inside the panel will trigger another loading which I don't think is what you want. This is why it is better you use the specific events provided by the material components.
This may be a little late, but perhaps it will help someone out there, who is looking for lazy loading (Lazy Rendering) via mat-expansion-panel.
"By default, the expansion panel content will be initialized even when the panel is closed. To instead defer initialization until the panel is open, the content should be provided as an ng-template:"
<mat-expansion-panel>
<mat-expansion-panel-header>
This is the expansion title
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
Some deferred content
</ng-template>
</mat-expansion-panel>
Source: https://material.angular.io/components/expansion/overview