Newer
Older
import {Directive, ElementRef, forwardRef, HostBinding, HostListener, Input, Renderer2} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
//https://github.com/KostyaTretyak/ng-stack/blob/master/projects/contenteditable/src/lib/contenteditable.directive.ts
@Directive({
selector: '[contenteditable]',
providers: [{provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => ContentEditableDirective), multi: true}],
})
export class ContentEditableDirective implements ControlValueAccessor {
@Input() propValueAccessor = 'textContent';
@HostBinding('attr.contenteditable') @Input() contenteditable = true;
private onChange: (value: string) => void;
private onTouched: () => void;
private removeDisabledState: () => void;
constructor(private elementRef: ElementRef, private renderer: Renderer2) {
}
@HostListener('input')
callOnChange() {
if (typeof this.onChange == 'function') {
this.onChange(this.elementRef.nativeElement[this.propValueAccessor]);
}
}
@HostListener('blur')
callOnTouched() {
if (typeof this.onTouched == 'function') {
this.onTouched();
}
}

Reid Givens
committed
@HostListener('paste', ['$event'])
onPaste($event) {
// after the paste, remove all the formatting
setTimeout(() => {
for(let el of this.elementRef.nativeElement.children) {
this.clearAttr(el);
}

Reid Givens
committed
}, 500);
}
clearAttr(el: any) {
this.renderer.removeAttribute(el, 'style');
this.renderer.removeAttribute(el, 'class');
this.renderer.removeAttribute(el, 'id');
for (let e of el.children) {
this.clearAttr(e);
}
}
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
* Writes a new value to the element.
* This method will be called by the forms API to write
* to the view when programmatic (model -> view) changes are requested.
*
* See: [ControlValueAccessor](https://angular.io/api/forms/ControlValueAccessor#members)
*/
writeValue(value: any): void {
const normalizedValue = value == null ? '' : value;
this.renderer.setProperty(this.elementRef.nativeElement, this.propValueAccessor, normalizedValue);
}
/**
* Registers a callback function that should be called when
* the control's value changes in the UI.
*
* This is called by the forms API on initialization so it can update
* the form model when values propagate from the view (view -> model).
*/
registerOnChange(fn: () => void): void {
this.onChange = fn;
}
/**
* Registers a callback function that should be called when the control receives a blur event.
* This is called by the forms API on initialization so it can update the form model on blur.
*/
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
/**
* This function is called by the forms API when the control status changes to or from "DISABLED".
* Depending on the value, it should enable or disable the appropriate DOM element.
*/
setDisabledState(isDisabled: boolean): void {
if (isDisabled) {
this.renderer.setAttribute(this.elementRef.nativeElement, 'disabled', 'true');
this.removeDisabledState = this.renderer.listen(
this.elementRef.nativeElement,
'keydown',
this.listenerDisabledState
);
} else {
if (this.removeDisabledState) {
this.renderer.removeAttribute(this.elementRef.nativeElement, 'disabled');
this.removeDisabledState();
}
}
}
private listenerDisabledState(e: KeyboardEvent) {
e.preventDefault();
}
}