66 * found in the LICENSE file at https://angular.io/license
77 */
88
9+ import { coerceBooleanProperty } from '@angular/cdk/coercion' ;
910import {
1011 Directive ,
1112 ElementRef ,
@@ -35,10 +36,14 @@ import {fromEvent, Subject} from 'rxjs';
3536export class CdkTextareaAutosize implements AfterViewInit , DoCheck , OnDestroy {
3637 /** Keep track of the previous textarea value to avoid resizing when the value hasn't changed. */
3738 private _previousValue : string ;
39+ private _initialHeight : string | null ;
3840 private readonly _destroyed = new Subject < void > ( ) ;
3941
4042 private _minRows : number ;
4143 private _maxRows : number ;
44+ private _enabled : boolean = true ;
45+
46+ private _textareaElement : HTMLTextAreaElement ;
4247
4348 /** Minimum amount of rows in the textarea. */
4449 @Input ( 'cdkAutosizeMinRows' )
@@ -56,13 +61,28 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
5661 this . _setMaxHeight ( ) ;
5762 }
5863
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+
5977 /** Cached height of a textarea with a single row. */
6078 private _cachedLineHeight : number ;
6179
6280 constructor (
6381 private _elementRef : ElementRef ,
6482 private _platform : Platform ,
65- private _ngZone : NgZone ) { }
83+ private _ngZone : NgZone ) {
84+ this . _textareaElement = this . _elementRef . nativeElement as HTMLTextAreaElement ;
85+ }
6686
6787 /** Sets the minimum height of the textarea as determined by minRows. */
6888 _setMinHeight ( ) : void {
@@ -86,6 +106,9 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
86106
87107 ngAfterViewInit ( ) {
88108 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+
89112 this . resizeToFitContent ( ) ;
90113
91114 this . _ngZone . runOutsideAngular ( ( ) => {
@@ -103,8 +126,7 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
103126
104127 /** Sets a style property on the textarea element. */
105128 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 ;
108130 }
109131
110132 /**
@@ -119,10 +141,8 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
119141 return ;
120142 }
121143
122- let textarea = this . _elementRef . nativeElement as HTMLTextAreaElement ;
123-
124144 // 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 ;
126146 textareaClone . rows = 1 ;
127147
128148 // 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 {
143163 // See Firefox bug report: https://bugzilla.mozilla.org/show_bug.cgi?id=33654
144164 textareaClone . style . overflow = 'hidden' ;
145165
146- textarea . parentNode ! . appendChild ( textareaClone ) ;
166+ this . _textareaElement . parentNode ! . appendChild ( textareaClone ) ;
147167 this . _cachedLineHeight = textareaClone . clientHeight ;
148- textarea . parentNode ! . removeChild ( textareaClone ) ;
168+ this . _textareaElement . parentNode ! . removeChild ( textareaClone ) ;
149169
150170 // Min and max heights have to be re-calculated if the cached line height changes
151171 this . _setMinHeight ( ) ;
@@ -164,6 +184,11 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
164184 * recalculated only if the value changed since the last call.
165185 */
166186 resizeToFitContent ( force : boolean = false ) {
187+ // If autosizing is disabled, just skip everything else
188+ if ( ! this . _enabled ) {
189+ return ;
190+ }
191+
167192 this . _cacheTextareaLineHeight ( ) ;
168193
169194 // 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 {
217242 this . _previousValue = value ;
218243 }
219244
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+
220257 _noopInputHandler ( ) {
221258 // no-op handler that ensures we're running change detection on input events.
222259 }
0 commit comments