/*
* @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;
}
}