import { Directive, ElementRef, Renderer2, Injector, OnInit, Input, AfterViewInit, OnDestroy, OnChanges, SimpleChanges, Output, ViewContainerRef, TemplateRef, NgZone } from '@angular/core'; import { EventEmitter } from '@angular/core'; @Directive({ selector: '[input-append]', }) export class InputAppendDirective implements OnInit, AfterViewInit, OnDestroy { private _enableAppend = true; // 相当于启用禁用此功能 @Input('input-append') set enableAppend(value: string | boolean) { if (value === '' || value) { this._enableAppend = true; // 需要 if (!this.appendWrapElement) { this.createStruct(); } } else { this._enableAppend = false; if (this.appendWrapElement) { this.resetStruct(); } } } get enableAppend() { return this._enableAppend; } // 追加到哪个类型下 TextBox、MultiTextBox、 StaticText @Input() inputAppendControlType = 'InputGroup'; // 根据类型不一样,在控件处于禁用、只读时,决定颜色是否可用 // 有两种:按钮 button 文本 text private _appendType = 'button'; @Input() set inputAppendType(value: string) { if (value) { if (['button', 'text'].findIndex(item => item == value) < 0) { // 类型在支持范围内 value = 'button'; } if (value != this._appendType) { if (this.appendWrapElement) { // 移除原来,追加新的 this.render.removeClass(this.appendWrapElement, 'input-append-' + this._appendType); this.render.addClass(this.appendWrapElement, 'input-append-' + value); if (this._appendType == 'button') { // 原来是按钮 if (this.clickHandler) { this.clickHandler(); this.clickHandler = null; } } else { this.clickHandler = this.render.listen(this.appendWrapElement, 'click', (ev) => { this.inputAppendClickEvent.emit(ev); }); } } this._appendType = value; } } } get inputAppendType() { return this._appendType; } // 追加的文本 private _inputAppendText = ''; @Input() set inputAppendText(value: string) { if (value != this._inputAppendText) { this._inputAppendText = value; if (this.appendWrapElement && this._enableAppend) { this.render.removeChild(this.appendWrapElement, this.appendTextElement); this.appendTextElement.innerHTML = value; this.render.appendChild(this.appendWrapElement, this.appendTextElement); } else { this.createStruct(); } } } get inputAppendText() { return this._inputAppendText; } // 模板 // @Input() inputAppendTmpl: TemplateRef; private _disabled = false; @Input() set inputAppendDisabled(value) { if (value != this._disabled) { this._disabled = value; if (this.appendWrapElement) { value && this.render.addClass(this.appendWrapElement, this.disabledCls); !value && this.render.removeClass(this.appendWrapElement, this.disabledCls); } } } get inputAppendDisabled() { return this._disabled; } /* * 文本点击事件 */ @Output() inputAppendClickEvent = new EventEmitter(); // 标记native的外层 private elWrapElement = null; // 标记元素 private appendWrapElement = null; // 暂时不用 private appendTextElement = null; private clickHandler = null; private disabledCls = 'f-state-disabled'; private ngZone: NgZone = null; // private ngControl: NgControl; constructor(private viewRef: ViewContainerRef, private el: ElementRef, private render: Renderer2, private injector: Injector) { this.ngZone = this.injector.get(NgZone); } ngOnInit() { //this.ngControl = this.injector.get(NgControl, null); } ngAfterViewInit() { this.createStruct(); } ngOnDestroy() { //this.resetStruct(); if (this.clickHandler) { this.clickHandler(); this.clickHandler = null; } if (this.appendWrapElement) { this.appendWrapElement.remove(); this.appendWrapElement = null; } if (this.elWrapElement) { this.elWrapElement.remove(); this.elWrapElement = null; } } /** * 重置 */ private resetStruct() { if (this.clickHandler) { this.clickHandler(); this.clickHandler = null; } // 分类型移除不同新增加的结构或样式 switch (this.inputAppendControlType) { case 'StaticText': this.render.removeClass(this.el.nativeElement, 'f-cmp-static-text-input-append'); break; case 'TextBox': case 'MultiTextBox': if (this.elWrapElement) { let wrapParent = this.render.parentNode(this.elWrapElement); this.render.appendChild(wrapParent, this.el.nativeElement); this.elWrapElement.remove(); this.elWrapElement = null; } break; } if (this.appendWrapElement) { this.appendWrapElement.remove(); this.appendWrapElement = null; } } /** * 创建 */ private createStruct() { if (!this.inputAppendText || !this.enableAppend || this.appendWrapElement) { return; } const buttonWrap = this.render.createElement('div'); buttonWrap.className = 'input-group-append input-append-wrapper'; buttonWrap.className += ' input-append-' + this.inputAppendType; if (this._disabled) { buttonWrap.className += ' ' + this.disabledCls; } const buttonTextWrap = this.render.createElement('div'); buttonTextWrap.className = 'input-group-text'; buttonTextWrap.innerHTML = this.inputAppendText; this.appendTextElement = buttonTextWrap; this.appendWrapElement = buttonWrap; this.render.appendChild(buttonWrap, buttonTextWrap); switch (this.inputAppendControlType) { case 'StaticText': // 此时还没有生成内部的样式 // let textareaEl = this.el.nativeElement.querySelector('.f-form-control-textarea'); this.render.addClass(this.el.nativeElement, 'f-cmp-static-text-input-append' + (this._disabled ? ' ' + this.disabledCls : '')); this.render.appendChild(this.el.nativeElement, buttonWrap); break; case 'TextBox': case 'MultiTextBox': let textParent = this.render.parentNode(this.el.nativeElement); const inputWrap = this.render.createElement('div'); inputWrap.className = 'f-cmp-text-input-append' + (this._disabled ? ' ' + this.disabledCls : ''); if (this.el.nativeElement.outerHTML.indexOf('textarea') > -1) { inputWrap.className = 'f-cmp-textarea-input-append' + (this._disabled ? ' ' + this.disabledCls : ''); } this.elWrapElement = inputWrap; this.render.appendChild(inputWrap, this.el.nativeElement); this.render.appendChild(inputWrap, buttonWrap); this.render.appendChild(textParent, inputWrap); break; default: // 存在类似下拉这样的控件,内部调用input-group结构还没有初始化 let inputGroupEl = this.el.nativeElement.querySelector('.input-group'); if (inputGroupEl) { this.render.appendChild(inputGroupEl, buttonWrap); } else { if (this.ngZone) { this.ngZone.runOutsideAngular(() => { setTimeout(() => { let inputGroupEl2 = this.el.nativeElement.querySelector('.input-group'); this.render.appendChild(inputGroupEl2, buttonWrap); }); }); } } } if (this.inputAppendType == 'button') { this.clickHandler = this.render.listen(this.appendWrapElement, 'click', (ev) => { this.inputAppendClickEvent.emit(ev); }); } } }