6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
+ import { coerceBooleanProperty } from '@angular/cdk/coercion' ;
9
10
import {
10
11
Directive ,
11
12
ElementRef ,
@@ -35,10 +36,14 @@ import {fromEvent, Subject} from 'rxjs';
35
36
export class CdkTextareaAutosize implements AfterViewInit , DoCheck , OnDestroy {
36
37
/** Keep track of the previous textarea value to avoid resizing when the value hasn't changed. */
37
38
private _previousValue : string ;
39
+ private _initialHeight : string | null ;
38
40
private readonly _destroyed = new Subject < void > ( ) ;
39
41
40
42
private _minRows : number ;
41
43
private _maxRows : number ;
44
+ private _enabled : boolean = true ;
45
+
46
+ private _textareaElement : HTMLTextAreaElement ;
42
47
43
48
/** Minimum amount of rows in the textarea. */
44
49
@Input ( 'cdkAutosizeMinRows' )
@@ -56,13 +61,28 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
56
61
this . _setMaxHeight ( ) ;
57
62
}
58
63
64
+ /** Whether autosizing is enabled or not */
65
+ @Input ( 'cdkTextareaAutosize' )
66
+ get enabled ( ) : boolean { return this . _enabled ; }
67
+ set enabled ( value : boolean ) {
68
+ value = coerceBooleanProperty ( value ) ;
69
+
70
+ // Only act if the actual value changed. This specifically helps to not run
71
+ // resizeToFitContent too early (i.e. before ngAfterViewInit)
72
+ if ( this . _enabled !== value ) {
73
+ ( this . _enabled = value ) ? this . resizeToFitContent ( true ) : this . reset ( ) ;
74
+ }
75
+ }
76
+
59
77
/** Cached height of a textarea with a single row. */
60
78
private _cachedLineHeight : number ;
61
79
62
80
constructor (
63
81
private _elementRef : ElementRef ,
64
82
private _platform : Platform ,
65
- private _ngZone : NgZone ) { }
83
+ private _ngZone : NgZone ) {
84
+ this . _textareaElement = this . _elementRef . nativeElement as HTMLTextAreaElement ;
85
+ }
66
86
67
87
/** Sets the minimum height of the textarea as determined by minRows. */
68
88
_setMinHeight ( ) : void {
@@ -86,6 +106,9 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
86
106
87
107
ngAfterViewInit ( ) {
88
108
if ( this . _platform . isBrowser ) {
109
+ // Remember the height which we started with in case autosizing is disabled
110
+ this . _initialHeight = this . _textareaElement . style . height ;
111
+
89
112
this . resizeToFitContent ( ) ;
90
113
91
114
this . _ngZone . runOutsideAngular ( ( ) => {
@@ -103,8 +126,7 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
103
126
104
127
/** Sets a style property on the textarea element. */
105
128
private _setTextareaStyle ( property : string , value : string ) : void {
106
- const textarea = this . _elementRef . nativeElement as HTMLTextAreaElement ;
107
- textarea . style [ property ] = value ;
129
+ this . _textareaElement . style [ property ] = value ;
108
130
}
109
131
110
132
/**
@@ -119,10 +141,8 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
119
141
return ;
120
142
}
121
143
122
- let textarea = this . _elementRef . nativeElement as HTMLTextAreaElement ;
123
-
124
144
// Use a clone element because we have to override some styles.
125
- let textareaClone = textarea . cloneNode ( false ) as HTMLTextAreaElement ;
145
+ let textareaClone = this . _textareaElement . cloneNode ( false ) as HTMLTextAreaElement ;
126
146
textareaClone . rows = 1 ;
127
147
128
148
// Use `position: absolute` so that this doesn't cause a browser layout and use
@@ -143,9 +163,9 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
143
163
// See Firefox bug report: https://bugzilla.mozilla.org/show_bug.cgi?id=33654
144
164
textareaClone . style . overflow = 'hidden' ;
145
165
146
- textarea . parentNode ! . appendChild ( textareaClone ) ;
166
+ this . _textareaElement . parentNode ! . appendChild ( textareaClone ) ;
147
167
this . _cachedLineHeight = textareaClone . clientHeight ;
148
- textarea . parentNode ! . removeChild ( textareaClone ) ;
168
+ this . _textareaElement . parentNode ! . removeChild ( textareaClone ) ;
149
169
150
170
// Min and max heights have to be re-calculated if the cached line height changes
151
171
this . _setMinHeight ( ) ;
@@ -164,6 +184,11 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
164
184
* recalculated only if the value changed since the last call.
165
185
*/
166
186
resizeToFitContent ( force : boolean = false ) {
187
+ // If autosizing is disabled, just skip everything else
188
+ if ( ! this . _enabled ) {
189
+ return ;
190
+ }
191
+
167
192
this . _cacheTextareaLineHeight ( ) ;
168
193
169
194
// If we haven't determined the line-height yet, we know we're still hidden and there's no point
@@ -217,6 +242,18 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
217
242
this . _previousValue = value ;
218
243
}
219
244
245
+ /**
246
+ * Resets the textarea to it's original size
247
+ */
248
+ reset ( ) {
249
+ // Do not try to change the textarea, if the initialHeight has not been determined yet
250
+ // This might potentially remove styles when reset() is called before ngAfterViewInit
251
+ if ( this . _initialHeight === undefined ) {
252
+ return ;
253
+ }
254
+ this . _textareaElement . style . height = this . _initialHeight ;
255
+ }
256
+
220
257
_noopInputHandler ( ) {
221
258
// no-op handler that ensures we're running change detection on input events.
222
259
}
0 commit comments