import { AfterViewInit , ChangeDetectionStrategy , ChangeDetectorRef , Component , ElementRef , forwardRef , HostListener , Input , Renderer2 , ViewChild } from '@angular/core' ; import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ; import * as util from '../../util' ; const noop = ( _ ) => { } ; @ Component ( { selector : 'auto-grow-input' , templateUrl : './auto-grow-input.component.html' , changeDetection : ChangeDetectionStrategy . OnPush , providers : [ { provide : NG_VALUE_ACCESSOR , useExisting : forwardRef ( ( ) => AutoGrowInputComponent ) , multi : true } ] , styleUrls : [ './auto-grow-input.component.scss' ] } ) export class AutoGrowInputComponent implements ControlValueAccessor , AfterViewInit { @ Input ( ) maxParentWidthPercent ; @ Input ( ) maxParentWidthOffset ; @ Input ( ) minWidth : number = 100 ; @ Input ( ) css : string ; @ Input ( ) selectAfterInit = false ; @ ViewChild ( 'inputControl' , { static : true } ) inputControl : ElementRef < HTMLInputElement > ; disabled : boolean ; get model ( ) : string { return this . _model ; } set model ( value ) { if ( this . _model === value ) { return ; } this . _model = value ; } private _model : string ; private _originalModel : string ; private _onChanged = noop ; private _onTouched = noop ; private _inEditMode = false ; constructor ( private _cdRef , private _renderer ) { } ngAfterViewInit ( ) { if ( this . selectAfterInit ) { setTimeout ( ( ) => { this . inputControl . nativeElement . select ( ) ; this . selectAfterInit = false ; } ) ; } } registerOnChange ( fn ) { this . _onChanged = fn ; } registerOnTouched ( fn ) { this . _onTouched = fn ; } setDisabledState ( isDisabled ) { if ( this . disabled === isDisabled ) { return ; } this . disabled = isDisabled ; this . _cdRef . markForCheck ( ) ; } @ HostListener ( 'window:resize' ) windowResize ( ) { this . calculateTextWidth ( this . _model ) ; } writeValue ( obj ) { if ( this . model === obj ) { return ; } this . _model = obj ; this . _originalModel = obj ; this . calculateTextWidth ( this . _model ) ; this . _cdRef . markForCheck ( ) ; } focus ( ) { setTimeout ( ( ) => { this . inputControl . nativeElement . focus ( ) ; } ) ; } inputFocus ( ) { this . _inEditMode = true ; this . calculateTextWidth ( this . model ) ; this . _onTouched ( this ) ; } blur ( ) { this . _inEditMode = false ; if ( ! util . isValidName ( this . _model ) || this . _model . trim ( ) === this . _originalModel ) { this . _model = this . _originalModel ; this . calculateTextWidth ( this . _model ) ; this . _cdRef . markForCheck ( ) ; return ; } this . _originalModel = this . _model ; this . calculateTextWidth ( this . _model ) ; this . _onChanged ( this . _model ) ; } keyEnter ( event ) { event . target . blur ( ) ; } calculateTextWidth ( text ) { const htmlInput = this . inputControl . nativeElement as HTMLInputElement ; let maxWidth = htmlInput . parentElement . parentElement . offsetWidth ; if ( this . maxParentWidthPercent ) { maxWidth *= this . maxParentWidthPercent ; } else if ( this . maxParentWidthOffset ) { maxWidth -= this . maxParentWidthOffset ; } maxWidth = Math . max ( this . minWidth , maxWidth ) ; let textWidth = util . getContentWidth ( window . getComputedStyle ( htmlInput ) , text ) * 1.01 ; if ( this . _inEditMode ) { textWidth += util . getContentWidth ( window . getComputedStyle ( htmlInput ) , 'W' ) * 1.1 ; } this . _renderer . setStyle ( htmlInput , 'width' , Math . min ( maxWidth , textWidth ) + 'px' ) ; } }