import { AfterViewInit , Directive , ElementRef , forwardRef , HostListener , Input , OnInit , ViewChild } from '@angular/core' ; import { ControlValueAccessor , FormControl , NG_VALUE_ACCESSOR } from '@angular/forms' ; import { FormatterParserCollectorService } from './formatter-parser.service' ; import { InputContextService } from './input-context.service' ; import { IFormatterParserConfig } from './struct/formatter-parser-config' ; import { IFormatterParserFn } from './struct/formatter-parser-function' ; declare var Ionic ; const CONTROL_VALUE_ACCESSOR = { name : 'formatterParserValueAccessor' , provide : NG_VALUE_ACCESSOR , useExisting : forwardRef ( ( ) => FormatterParserDirective ) , multi : true } ; @ Directive ( { selector : '[formatterParser]' , providers : [ CONTROL_VALUE_ACCESSOR ] } ) export class FormatterParserDirective implements ControlValueAccessor , AfterViewInit { @ Input ( ) formatterParser : IFormatterParserConfig ; @ Input ( ) formControlName : string ; protected formControl : FormControl ; protected inputElement : HTMLInputElement ; private formatterParserView : IFormatterParserFn [ ] = [ ] ; private formatterParserModel : IFormatterParserFn [ ] = [ ] ; private onTouch : Function ; private onModelChange : Function ; constructor ( private _elementRef , private fps , private inputContext ) { } registerOnTouched ( fn ) { this . onTouch = fn ; } registerOnChange ( fn ) { this . onModelChange = fn ; } ngAfterViewInit ( ) { this . inputElement = this . getInputElementRef ( ) ; this . updateFormatterAndParser ( ) ; } @ HostListener ( 'input' , [ '$event' ] ) onControlInput ( $event ) { const rawValue = this . inputElement . value ; if ( this . onTouch ) { this . onTouch ( ) ; } this . inputElement . value = this . formatterParserView . reduce ( ( state , transform ) => transform ( state ) . result , rawValue || null ) ; const modelValue = this . formatterParserModel . reduce ( ( state , transform ) => transform ( state ) . result , rawValue || null ) ; if ( this . onModelChange ) { this . onModelChange ( modelValue ) ; } this . inputContext . setSelection ( this . inputElement ) ; } writeValue ( rawValue ) { if ( this . inputElement ) { this . inputElement . value = this . formatterParserView . reduce ( ( state , transform ) => transform ( state ) . result , rawValue ) ; } const modelValue = this . formatterParserModel . reduce ( ( state , transform ) => transform ( state ) . result , rawValue ) ; if ( rawValue !== modelValue ) { if ( this . onModelChange ) { this . onModelChange ( modelValue ) ; } } } updateFormatterAndParser ( ) { this . formatterParserView = [ ] ; this . formatterParserModel = [ ] ; if ( ! this . formatterParser ) { return ; } if ( 'formatterParser' in this . formatterParser ) { this . formatterParser . formatterParser . forEach ( ( formatterConfig ) => { const targetBoth = 2 ; const fPF = this . fps . getFormatParseFunction ( formatterConfig . name , formatterConfig . params ) ; const t = ( formatterConfig . target === undefined ) ? targetBoth : formatterConfig . target ; if ( t === 1 || t === 2 ) { this . formatterParserModel . push ( fPF ) ; } if ( ( t === 0 || t === 2 ) ) { this . formatterParserView . push ( fPF ) ; } } ) ; } } private getInputElementRef ( ) { let input ; if ( this . _elementRef . nativeElement . tagName === 'INPUT' ) { input = this . _elementRef . nativeElement ; } else { input = this . _elementRef . nativeElement . getElementsByTagName ( 'INPUT' ) [ 0 ] ; } if ( ! input ) { throw new Error ( 'You can applied the "formatterParser" directive only on inputs or elements containing inputs' ) ; } return input ; } }