Change ion-input type. Show/Hide password directive/component

#1

Hi, I’m trying to implement a show/hide password similar to this one.

The problem I’m facing is that the TextInput directive from angular 2 has it’s type set method private so I can’t change the input type dynamically.

<show-hide-container>
    <ion-input type="password" placeholder="Password"></ion-input>
</show-hide-container>
export class ShowHideContainer
{
  show = false;

  @ContentChild(TextInput) ion_input: TextInput;

  constructor(){}

  toggleShow()
  {
    this.show = !this.show;
    if (this.show){
      // type is private!!!
      this.ion_input.type("text");
    }
    else {
      this.ion_input.type("password");
    }
  }
}

any help would be much appreciated!

#2

Hi!
Change your directive [show-hide-input] like this:

import { Directive, HostBinding, ElementRef } from '@angular/core';

@Directive({
    selector: '[show-hide-input]'
})
export class ShowHideInput {

    @HostBinding() type: string;

    constructor(private el: ElementRef) {
        this.type = 'password';
    }

    changeType(type: string) {  // in your case function name is type
        this.type = type;
        this.el.nativeElement.children[0].type = this.type; // change type for input inside the ion-input
    }

}

And in your template:

<show-hide-container>
    <ion-input type="password" placeholder="Password" show-hide-input></ion-input> // add the directive show-hide-input
</show-hide-container>

It works for me.

1 Like
#3

Thank you so much!

At first I thought I could avoid using another directive (show-hide-input) and use the <ion-input> instead. But the methods I needed to access were private within the <ion-input> component, so it seems there’s no choice but to use the show-hide-input directive for this.

Another issue i found is that if you are using <ion-item> component along with <ion-input> you should put both of them inside the <show-hide-container>

THIS DOESN’T WORK

<ion-item>
  <show-hide-container>
    <ion-input type="password" placeholder="Password" formControlName="password" show-hide-input></ion-input>
  </show-hide-container>
</ion-item>

THIS WORKS

<show-hide-container>
  <ion-item>
    <ion-input type="password" placeholder="Password" formControlName="password" show-hide-input></ion-input>
  </ion-item>
</show-hide-container>

Having said that, it would be awesome if the guys from the ionic team could write a post or guide about the proper way to extend and create custom directives for the ionic framework. I believe there are tons of developers like me that want to crete awesome stuff with ionic and at the end these custom directives and UI/UX widgets will be super useful for the community.

The community is what makes ionic great.

1 Like
#4

There is no need to do all that is written above, just do this

in .html

 <ion-item>
    <ion-label fixed>Password</ion-label>
    <ion-input #input type="password" [(ngModel)]="loginUtente.password"></ion-input>
  </ion-item>

<ion-item>
    <ion-label for="checkbox" *ngIf="!passwordCheckbox">show password</ion-label>
    <ion-label for="checkbox" *ngIf="passwordCheckbox">hide password</ion-label>
    <ion-checkbox  class="marginTop" id="checkbox" style="border-style: none;" [(ngModel)]="passwordCheckbox" (click)="showPassword(input)"></ion-checkbox>
  </ion-item>

in .ts

showPassword(input: any): any {
   input.type = input.type === 'password' ?  'text' : 'password';
  }

I hope to have helped

1 Like
#5

I would much prefer binding [type] instead of directly fooling with DOM attributes in showPassword() (which should rather be named toggleShowPassword() or something to indicate that it doesn’t just show the password).

#6

Using the approach of the OP’s accepted solution in the latest Ionic 2 version I get the following error:

Unhandled Promise rejection: Template parse errors:
Can’t bind to ‘type’ since it isn’t a known property of ‘ion-input’.

I created two separate .ts files for both the container and input attribute directive & imported them into the declarations of app.module.ts.

Does anyone know to resolve this? Thanks!

#7

Hi thorgalle, this is another simple solution. I hope helped.

login.html

<ion-item>
        <ion-input [type]="getType()"></ion-input>
        <ion-icon name="eye" item-right (click)="toggleTextPassword()"></ion-icon>
 </ion-item>

login.ts

export class LoginPage {
  isActiveToggleTextPassword: Boolean = true;
  public toggleTextPassword(): void{
      this.isActiveToggleTextPassword = (this.isActiveToggleTextPassword==true)?false:true;
  }
  public getType() {
      return this.isActiveToggleTextPassword ? 'password' : 'text';
  }
}
1 Like
#8

I don’t know why this would be better then this:

HTML

<ion-input [type]="password_type" placeholder="Password" name="password" [(ngModel)]="password" required></ion-input>
<ion-icon name="eye" item-right (click)="togglePasswordMode()"></ion-icon>

TS

password_type: string = 'password';

togglePasswordMode() {   
   this.password_type = this.password_type === 'text' ? 'password' : 'text';
}
3 Likes
#9

I am also getting this issue. I thought it was related to lazy loading but maybe it is the ionic version?

#10

This was a easy, 100% effective solution.
minor change on my end

togglePasswordMode() {   
   this.password_type === 'text' ? 'password' : 'text';
}

Not sure why you had the extra this.password_type =
Typo or just a personal preference for doing things?

#11

Typo :slight_smile: thanks

#12

No problem. Thanks for the pragmatic solution

1 Like
#13

Hey! I am getting errors with this. Error: Template parse errors: Can't bind to 'type' since it isn't a known property of 'ion-input'.

I recently updated to Ionic4. Is that the reason? Any update

#14

Sorry I figured it out… Change the @HostBinding to @Input