Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
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();
}
}
/**
* 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();
}
}