/* * @Author: 疯狂秀才(Lucas Huang) * @Date: 2019-08-08 18:53:41 * @LastEditors: 疯狂秀才(Lucas Huang) * @LastEditTime: 2019-11-27 11:19:44 * @QQ: 1055818239 * @Version: v0.0.1 */ import { SimpleChanges, Renderer2, forwardRef, Injector, HostBinding, ChangeDetectorRef } from '@angular/core'; import { NgZone, ViewEncapsulation, TemplateRef } from '@angular/core'; import { Component, OnInit, Output, EventEmitter, ElementRef, Input, AfterViewInit, ViewChild, OnChanges } from '@angular/core'; import { NG_VALUE_ACCESSOR, ControlValueAccessor, NgControl, MaxLengthValidator } from '@angular/forms'; export const INPUT_GROUP_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputGroupComponent), multi: true }; @Component({ selector: 'farrisui-input-group, input-group, farris-input-group', template: `
`, styles: [ ` .input-group { flex-wrap: nowrap; } .input-group-text { cursor: pointer; } .input-group-clear { cursor: pointer; background: #fff !important; } .input-group-text:hover { background: #ccc; } ` ], // .input-group-clear:hover { // background: #e9ecef !important; // } providers: [INPUT_GROUP_VALUE_ACCESSOR], encapsulation: ViewEncapsulation.None }) export class InputGroupComponent implements OnInit, AfterViewInit, OnChanges, ControlValueAccessor { @HostBinding('class.f-cmp-inputgroup') @Input() autocomplete = 'off'; showClearButton = false; ngControl: NgControl; @Input() value = ''; /** 只读 */ @Input() readonly = false; /** 禁用 */ @Input() disabled = false; /** 允许编辑 */ @Input() editable = true; /** 启用清除按钮 */ @Input() enableClear = true; /** 扩展按钮 */ @Input() groupText = ''; /** 自定义CLASS */ @Input() customCls = ''; /** 当组件禁用或只读时显示后边的按钮 */ @Input() showButtonWhenDisabled = false; /** 启用提示信息 */ @Input() placeholder = ''; /** 文本在输入框中的对齐方式 */ @Input() textAlign = 'left'; @Input() groupTextTemplate: TemplateRef; @Input() isPassword = false; @Input() enableViewPassword = true; @Input() minLength: number | undefined = undefined; @Input() maxLength: number | undefined = undefined; @Input() tabIndex: number; @Input() enableTitle = true; /** 扩展信息;在输入框前面 显示 ① 图标鼠标滑过后显示 */ @Input() useExtendInfo = false; @Input() extendInfo = ''; @Input() forcePlaceholder = false; @Output() updateExtendInfo = new EventEmitter(); @Output() clear = new EventEmitter(); @Output() valueChange = new EventEmitter(); @Output() clickHandle = new EventEmitter(); @Output() blurHandle = new EventEmitter(); @Output() focusHandle = new EventEmitter(); @Output() enterHandle = new EventEmitter(); @Output() iconMouseEnter = new EventEmitter(); @Output() iconMouseLeave = new EventEmitter(); @Output() keyupHandle = new EventEmitter(); @Output() keydownHandle = new EventEmitter(); @Output() inputClick = new EventEmitter(); @ViewChild('inputGroup') inputGroup: ElementRef; @ViewChild('textbox') textbox: ElementRef; inputType = 'text'; private state: boolean; cd: ChangeDetectorRef = null; private focusCls = 'f-state-focus'; onModelChange = (obj: any) => { }; onModelTouched = (val: any) => { }; constructor( public el: ElementRef, private renderer: Renderer2, private ngZone: NgZone, private injector: Injector ) { this.cd = this.injector.get(ChangeDetectorRef); } ngOnInit() { if (!this.groupText) { this.renderer.setStyle( this.el.nativeElement.querySelector('.input-group-append'), 'margin-left', '0' ); } this.initSmartPassword(); // if (!this.editable) { // this.readonly = true // } } ngAfterViewInit() { this.ngZone.runOutsideAngular(() => { if (this.enableClear) { this.inputGroup.nativeElement.addEventListener( 'mouseenter', this.onMouseEnter.bind(this) ); this.inputGroup.nativeElement.addEventListener( 'mouseleave', this.onMouseLeave.bind(this) ); } // this.textbox.nativeElement.addEventListener('focus', (e) => { // if (!this.readonly && !this.disabled) { // this.renderer.addClass(this.inputGroup.nativeElement, this.focusCls); // this.focusHandle.emit(e); // } // }); }); } ngOnChanges(changes: SimpleChanges) { if (changes.groupText && !changes.groupText.isFirstChange()) { if (changes.groupText.currentValue) { this.renderer.setStyle( this.el.nativeElement.querySelector('.input-group-append'), 'margin-left', '-1' ); } } } ngModelChange(val: any) { // console.log(val); } private initSmartPassword() { if (this.isPassword) { const openEyeICON = ''; const closeEyeICON = ''; this.groupText = closeEyeICON; if (!this.enableViewPassword) { this.groupText = ''; } this.inputType = 'password'; let openEyes = false; this.onClickHandle = ($event) => { openEyes = !openEyes; const inputtype = openEyes ? 'text' : 'password'; this.groupText = openEyes ? openEyeICON : closeEyeICON; this.inputType = inputtype; this.cd.detectChanges(); return false; }; } else { this.inputType = 'text'; } } onEnter($event: KeyboardEvent) { // if (this.editable) { // $event.stopPropagation(); // } this.enterHandle.emit({originalEvent: $event}); } onInputFocus($event) { if (this.disabled) { return; } else { this.renderer.addClass(this.inputGroup.nativeElement, this.focusCls); if (this.editable || !this.readonly) { this.focusHandle.emit($event); } } } onInputClick($event) { this.inputClick.emit($event); } onMouseEnter(event) { if (this.value) { if (!this.editable) { if (!this.state && !this.disabled) { this.showClearButton = true; } } else { if (!this.readonly && !this.disabled) { this.showClearButton = true; } } } if (this.showClearButton) { this.toggleClearIcon(event, true); } } onMouseLeave(event) { this.showClearButton = false; this.toggleClearIcon(event, false); } getStateCls() { if (this.disabled) { return { 'f-state-disabled': true }; } else { if (!this.editable) { return { 'f-state-editable': true, 'f-state-readonly': this.readonly }; } else { return { 'f-state-readonly': this.readonly }; } } } private toggleClearIcon(event: any, isShow = false) { const str = isShow ? '' : 'none'; const clearIcon = event.target.querySelector('.input-group-clear'); if (clearIcon) { clearIcon.style.display = str; } } onMouseOverInExtentInfo() { this.updateExtendInfo.emit(); } onMousedown($event: MouseEvent) { const target = $event.target as HTMLElement; if (target.tagName !== 'INPUT') { $event.preventDefault(); } $event.stopPropagation(); } onClearValue($event: any) { const flag1 = !this.readonly && !this.disabled && this.editable; const flag2 = !this.editable; $event.stopPropagation(); if (flag1 || flag2) { this.onValueChange('', false); this.showClearButton = false; this.clear.emit(); } } onBlur(event) { this.renderer.removeClass(this.inputGroup.nativeElement, this.focusCls); this.blurHandle.emit(event); event.stopPropagation(); return false; } onValueChange(val: string, emit = true) { if (this.value !== val) { this.value = val; this.onModelChange(val); this.onModelTouched(val); if (emit) { this.valueChange.emit(val); } } } onClickHandle(event: Event) { if (this.showButtonWhenDisabled || ((!this.editable || !this.readonly) && !this.disabled)) { this.clickHandle.emit({ originalEvent: event, value: this.value }); } // if (!this.editable) { // if (!this.disabled) { // this.clickHandle.emit({ // originalEvent: event, // value: this.value // }); // } // } else { // if (!this.readonly && !this.disabled) { // this.clickHandle.emit({ // originalEvent: event, // value: this.value // }); // } // } event.stopPropagation(); } onIconMouseEnter(e: MouseEvent) { this.iconMouseEnter.emit(e); } onIconMouseLeave(e: MouseEvent) { this.iconMouseLeave.emit(e); } focus() { this.textbox.nativeElement.focus(); } writeValue(obj: any): void { this.value = (obj === null || obj === undefined) ? '' : obj; this.textbox.nativeElement.value = this.value; // 在此处执行 onModelChange 则 pristine 状态变为 false 即非第一次加载;导至表单中的错误信息显示出来, // 如果必须要执行一次,需要重新ngControl 的状态 // this.onModelChange(obj); } registerOnChange(fn: any): void { this.onModelChange = fn; } registerOnTouched(fn: any): void { this.onModelTouched = fn; } setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; } setFocusToEnd() { const el = this.textbox.nativeElement; el.focus(); el.selectionStart = el.value.length; el.selectionEnd = el.value.length; } }