Angular2 - 复杂指令- *ngError

需求:

  • 想实现一个类似*ngIf 的指令 - 接受参数的模板指令
  • 下面代码效果
    • *ngError 接受一个正则表达式内部的string (不要 / / 的)
    • 指令内判断当前所在div(可编辑的)的内容符合正则 则触发向DOM里添加元素。
    • 之前触发后,当不符合时,去除元素Message
import {Directive, ViewContainerRef, TemplateRef } from 'angular2/core';
import {isPresent, isBlank, RegExp} from 'angular2/src/facade/lang';
import {MATERIAL_DIRECTIVES} from 'ng2-material/all';
import {makeTypeError} from 'angular2/src/facade/exceptions';


@Directive({
selector: '[ngError]',
inputs: ['ngError']
})
export class ngError {
private _condition: RegExp = null;
private _view = null;
private _content: any = null;
private _prevError: boolean = false;
private _error: boolean = false;

private _messageEl = null;

constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef) {
}

set ngError(newCondition: string) {

if (!!newCondition) {

this._condition = new RegExp(newCondition);
this._view = this._viewContainer.createEmbeddedView(this._templateRef);
this._view._view.renderFragment.nodes[0].addEventListener('blur', this.onBlur.bind(this));
}
else {
throw makeTypeError('The RegExp must have at leat one character.');
}
}


onBlur() {
this._content = this._view._view.renderFragment.nodes[0].lastChild;
this._error = this._condition.test(this._content.textContent);

if (this._error && this._prevError !== true) {
this._prevError = true;
this.addMessageElement();
} else if (this._error === false && this._prevError === true) {

this._prevError = false;
this.removeMessage();
}
}

addMessageElement() {
this._messageEl = document.createElement('div');
this._messageEl.id = "popupContainer";
this._messageEl.className = "md-padding";
this._messageEl.innerHTML = `<button md-raised-button class="md-warn md-hue-2">
Haha Warning Message Here!
</button>`;

this._viewContainer.element.nativeElement.parentElement.appendChild(this._messageEl);
}

removeMessage() {
this._viewContainer.element.nativeElement.parentElement.removeChild(this._messageEl);
}

}

用法

<div *ngError ="'a'" id="input" contenteditable> </div>

设想

我觉得以后会有大量的指令遵循这种模式

  1. 指令接受参数
  2. 指令判断参数
  3. DOM操作 或者 新组建初始化?(参见文章Angular2 - DynamicComponentLoader 用法)

此sample里由于我import angular里的DOM不成功,所以都是直接document来操作DOM。
如果Angular自己的DOM 模块是操作的 VM,应该用DOM模块

https://github.com/dreambo8563/node_angular2/blob/ng-pages/app/directives/error.ts