1
1
import { ControlValueAccessor , NG_VALUE_ACCESSOR } from "@angular/forms" ;
2
2
import { Directive , ElementRef , EventEmitter , Input , NgZone , Output , forwardRef } from '@angular/core' ;
3
+ import cloneDeep from "lodash.clonedeep" ;
4
+ import isEqual from 'lodash.isequal' ;
3
5
4
6
import FroalaEditor from 'froala-editor' ;
5
7
8
+ type FroalaOptions = Record < string , any > ;
9
+
6
10
@Directive ( {
7
11
selector : '[froalaEditor]' ,
8
12
exportAs : 'froalaEditor' ,
@@ -15,7 +19,7 @@ import FroalaEditor from 'froala-editor';
15
19
export class FroalaEditorDirective implements ControlValueAccessor {
16
20
17
21
// editor options
18
- private _opts : any = {
22
+ private _opts : FroalaOptions = {
19
23
immediateAngularModelUpdate : false ,
20
24
angularIgnoreAttrs : null
21
25
} ;
@@ -65,65 +69,25 @@ export class FroalaEditorDirective implements ControlValueAccessor {
65
69
// froalaEditor directive as input: store the editor options
66
70
@Input ( ) set froalaEditor ( opts : any ) {
67
71
this . _opts = this . clone ( opts || this . _opts ) ;
68
- this . _opts = { ...this . _opts } ;
69
72
}
70
73
71
- // TODO: replace clone method with better possible alternate
72
- private clone ( item ) {
73
- const me = this ;
74
- if ( ! item ) { return item ; } // null, undefined values check
75
-
76
- let types = [ Number , String , Boolean ] ,
77
- result ;
78
-
79
- // normalizing primitives if someone did new String('aaa'), or new Number('444');
80
- types . forEach ( function ( type ) {
81
- if ( item instanceof type ) {
82
- result = type ( item ) ;
83
- }
84
- } ) ;
85
-
86
- if ( typeof result == "undefined" ) {
87
- if ( Object . prototype . toString . call ( item ) === "[object Array]" ) {
88
- result = [ ] ;
89
- item . forEach ( function ( child , index , array ) {
90
- result [ index ] = me . clone ( child ) ;
91
- } ) ;
92
- } else if ( typeof item == "object" ) {
93
- // testing that this is DOM
94
- if ( item . nodeType && typeof item . cloneNode == "function" ) {
95
- result = item . cloneNode ( true ) ;
96
- } else if ( ! item . prototype ) { // check that this is a literal
97
- if ( item instanceof Date ) {
98
- result = new Date ( item ) ;
99
- } else {
100
- // it is an object literal
101
- result = { } ;
102
- for ( var i in item ) {
103
- result [ i ] = me . clone ( item [ i ] ) ;
104
- }
105
- }
106
- } else {
107
- if ( false && item . constructor ) {
108
- result = new item . constructor ( ) ;
109
- } else {
110
- result = item ;
111
- }
112
- }
113
- } else {
114
- result = item ;
115
- }
116
- }
117
- return result ;
74
+ // clone object
75
+ private clone ( opts : FroalaOptions ) : FroalaOptions {
76
+ return cloneDeep ( opts ) ;
118
77
}
119
78
// froalaModel directive as input: store initial editor content
120
79
@Input ( ) set froalaModel ( content : any ) {
121
80
this . updateEditor ( content ) ;
122
81
}
123
82
83
+ // exposing the editor
84
+ public get editor ( ) {
85
+ return this . _editor ;
86
+ }
87
+
124
88
// Update editor with model contents.
125
89
private updateEditor ( content : any ) {
126
- if ( JSON . stringify ( this . _oldModel ) == JSON . stringify ( content ) ) {
90
+ if ( isEqual ( this . _oldModel , content ) ) {
127
91
return ;
128
92
}
129
93
@@ -223,9 +187,7 @@ export class FroalaEditorDirective implements ControlValueAccessor {
223
187
if ( this . _editor . events ) {
224
188
// bind contentChange and keyup event to froalaModel
225
189
this . _editor . events . on ( 'contentChanged' , function ( ) {
226
- setTimeout ( function ( ) {
227
- self . updateModel ( ) ;
228
- } , 0 ) ;
190
+ self . updateModel ( ) ;
229
191
} ) ;
230
192
this . _editor . events . on ( 'mousedown' , function ( ) {
231
193
setTimeout ( function ( ) {
@@ -278,7 +240,11 @@ export class FroalaEditorDirective implements ControlValueAccessor {
278
240
}
279
241
280
242
private setHtml ( ) {
281
- this . _editor . html . set ( this . _model || "" ) ;
243
+ if ( this . _hasSpecialTag ) {
244
+ this . _editor . html . set ( this . _model || "" ) ;
245
+ } else {
246
+ this . _editor . html . set ( this . _oldModel || "" ) ;
247
+ }
282
248
283
249
// This will reset the undo stack everytime the model changes externally. Can we fix this?
284
250
this . _editor . undo . reset ( ) ;
@@ -291,6 +257,7 @@ export class FroalaEditorDirective implements ControlValueAccessor {
291
257
// Set initial content
292
258
if ( this . _model || this . _model == '' ) {
293
259
this . _oldModel = this . _model ;
260
+
294
261
if ( this . _hasSpecialTag ) {
295
262
296
263
let tags : Object = this . _model ;
@@ -317,7 +284,7 @@ export class FroalaEditorDirective implements ControlValueAccessor {
317
284
self . setHtml ( ) ;
318
285
}
319
286
}
320
- }
287
+ }
321
288
}
322
289
323
290
private destroyEditor ( ) {
0 commit comments