<!DOCTYPE html>
<html>

  <head>
    <base href="." />
    <title>angular playground</title>
    <link rel="stylesheet" href="style.css" />
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
    <script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script>
    <script src="https://unpkg.com/zone.js@0.8.26?main=browser"></script>
    <script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
    <script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
    <script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
    <script src="config.js"></script>
    <script>
    System.import('app')
      .catch(console.error.bind(console));
  </script>
  </head>

  <body>
    <my-app>
    loading...
  </my-app>
  </body>

</html>
/* Styles go here */

### Angular Starter Plunker - Typescript
var angularVersion = '@6.0.7';

System.config({
  transpiler: 'ts',
  typescriptOptions: {
    emitDecoratorMetadata: true,
    experimentalDecorators: true
  },
  meta: {
  'typescript': {
		"exports": "ts"
	  }
	},
  paths: {
    'npm:': 'https://unpkg.com/'
  },
  map: {
    app: "./src",
    '@angular/core': 'npm:@angular/core'+angularVersion+'/bundles/core.umd.js',
    '@angular/common': 'npm:@angular/common'+angularVersion+'/bundles/common.umd.js',
    '@angular/compiler': 'npm:@angular/compiler'+angularVersion+'/bundles/compiler.umd.js',
    '@angular/platform-browser': 'npm:@angular/platform-browser'+angularVersion+'/bundles/platform-browser.umd.js',
    '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic'+angularVersion+'/bundles/platform-browser-dynamic.umd.js',
    '@angular/http': 'npm:@angular/http'+angularVersion+'/bundles/http.umd.js',
    '@angular/router': 'npm:@angular/router'+angularVersion+'/bundles/router.umd.js',
    '@angular/forms': 'npm:@angular/forms'+angularVersion+'/bundles/forms.umd.js',
    '@angular/upgrade': 'npm:@angular/upgrade'+angularVersion+'/bundles/upgrade.umd.js',
    '@angular/upgrade/static': 'npm:@angular/upgrade'+angularVersion+'/bundles/upgrade-static.umd.js',

    // other libraries
    'rxjs':                      'npm:rxjs@6.2.1',
    'rxjs-compat':               'npm:rxjs-compat@6.2.1',
    'ts':                        'npm:plugin-typescript@8.0.0/lib/plugin.js',
    'typescript':                'npm:typescript@2.9.2/lib/typescript.js',
    'gijgo-angular-wrappers': 'npm:gijgo-angular-wrappers@1.9.8/index.ts',
    'gijgo': 'npm:gijgo',
    '@types/jquery': 'npm:@types/jquery',
    '@types/gijgo': 'npm:@types/gijgo'
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    },
    rxjs: {
        main: 'index.js',
        defaultExtension: 'js'
    },
    "rxjs/operators": {
        main: 'index.js',
        defaultExtension: 'js'
    }
  }
});
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';

platformBrowserDynamic().bootstrapModule(AppModule)
//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {FormsModule} from '@angular/forms';
import {PasswordInputComponent} from './password-input.component';

@Component({
  selector: 'my-app',
  template: `
    <div class="container">
      <h1>Angular Password Input Demo</h1>
      <hr>
      <form #f="ngForm">
      
        <p>
          Following "password-input" is the default one - 
          showing password on mouse-press and hiding it on release
        </p>
        <password-input name="password" ngModel></password-input>
        <p>Model = <b>{{ f.value.password || 'not set' }}</b></p>
        
        <br/>
        
        <p>
          Following "password-input" is showing <b>placeholder</b> usage
        </p>
        <password-input name="password2" ngModel placeholder="Enter your password here ..."></password-input>
        <p>Model = <b>{{ f.value.password2 || 'not set' }}</b></p>
        
        <br/>
        
        <p>
          Following "password-input" is showing <b>placeholder</b> usage and <b>click</b> 
          behaviour - toggle password view/hide on click
        </p>
        <password-input 
          name="password3" 
          ngModel 
          placeholder="Enter your password here ..."
          behaviour="click">
        </password-input>
        <p>Model = <b>{{ f.value.password3 || 'not set' }}</b></p>
        
      </form>
    </div>
  `,
})
export class App {
  
  password:string;
  
  constructor() {}
}

@NgModule({
  imports: [ BrowserModule, FormsModule ],
  declarations: [ App, PasswordInputComponent ],
  bootstrap: [ App ]
})
export class AppModule {}
import {
    Component,
    AfterViewInit,
    Input,
    ElementRef,
    ViewChild
} from '@angular/core';

import {
    ControlValueAccessor,
    NG_VALUE_ACCESSOR
} from '@angular/forms';


const noop = () => {
};

@Component({
    selector: 'password-input',
    template: `
    <div class="input-group mb-2 mr-sm-2 mb-sm-0">
        <input type="password" class="form-control" placeholder="{{placeholder}}" #input [(ngModel)]="value">
        <div class="input-group-addon" #toggler><i class="fa fa-eye"></i></div>
    </div>`,
    providers: [
        {provide: NG_VALUE_ACCESSOR, multi: true, useExisting: PasswordInputComponent}
    ]
})
export class PasswordInputComponent implements AfterViewInit, ControlValueAccessor {

    private _value: string;
    private _onChange: (_: any) => void = noop;

    @ViewChild('input') el: ElementRef;
    @ViewChild('toggler') toggler: ElementRef;
    @Input() placeholder: string;
    @Input() behaviour: string = 'press';


    get value(): any {
        return this._value;
    };

    set value(v: any) {
        if (v !== this._value) {
            this._value = v;
            this._onChange(v);
        }
    }

    ngAfterViewInit() {
        let __this = this;
        let textbox = __this.el.nativeElement;
        let toggler = __this.toggler.nativeElement;
        let togglerIcon = toggler.childNodes[0];

        if (__this.behaviour === 'press') {
            toggler.addEventListener('mousedown', (e) => {
                textbox.type = 'text';
                togglerIcon.classList.remove('fa-eye');
                togglerIcon.classList.add('fa-eye-slash');
            });
            toggler.addEventListener('mouseup', (e) => {
                textbox.type = 'password';
                togglerIcon.classList.remove('fa-eye-slash');
                togglerIcon.classList.add('fa-eye');
            });
        }

        if (__this.behaviour === 'click') {
            toggler.addEventListener('click', (e) => {
                textbox.type = textbox.type === 'password' ? 'text' : 'password';
                togglerIcon.classList.toggle('fa-eye');
                togglerIcon.classList.toggle('fa-eye-slash');
            });
        }
    }

    writeValue(value: any) {
        this._value = value;
    }

    registerOnChange(fn: (value: any) => void) {
        this._onChange = fn;
    }

    registerOnTouched(fn: any) {}

}