Skip to content

Commit 71876f8

Browse files
crisbetojelbourn
authored andcommitted
fix(autosize): not resizing on programmatic changes
Fixes the textarea autosize directive not resizing when the value is changed programmatically outside Angular (e.g. `element.value`) or when the form control is swapped out. Fixes #5247.
1 parent 43b7c34 commit 71876f8

File tree

2 files changed

+29
-16
lines changed

2 files changed

+29
-16
lines changed

src/lib/input/autosize.spec.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ describe('MdTextareaAutosize', () => {
170170
textarea = fixtureWithForms.nativeElement.querySelector('textarea');
171171
fixtureWithForms.detectChanges();
172172

173-
const previousHeight = textarea.clientHeight;
173+
const previousHeight = textarea.clientHeight;
174174

175175
fixtureWithForms.componentInstance.model = `
176176
And the silken, sad, uncertain rustling of each purple curtain
@@ -181,10 +181,27 @@ describe('MdTextareaAutosize', () => {
181181
This it is and nothing more.” `;
182182
fixtureWithForms.detectChanges();
183183
flushMicrotasks();
184+
fixtureWithForms.detectChanges();
184185

185186
expect(textarea.clientHeight)
186187
.toBeGreaterThan(previousHeight, 'Expected increased height when ngModel is updated.');
187188
}));
189+
190+
it('should resize when the textarea value is changed programmatically', fakeAsync(() => {
191+
const previousHeight = textarea.clientHeight;
192+
193+
textarea.value = `
194+
How much wood would a woodchuck chuck
195+
if a woodchuck could chuck wood?
196+
`;
197+
198+
fixture.detectChanges();
199+
flushMicrotasks();
200+
fixture.detectChanges();
201+
202+
expect(textarea.clientHeight)
203+
.toBeGreaterThan(previousHeight, 'Expected the textarea height to have increased.');
204+
}));
188205
});
189206

190207

src/lib/input/autosize.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Directive, ElementRef, Input, AfterViewInit, Optional, Self} from '@angular/core';
10-
import {NgControl} from '@angular/forms';
9+
import {Directive, ElementRef, Input, AfterViewInit, DoCheck} from '@angular/core';
1110
import {Platform} from '@angular/cdk/platform';
1211

1312

@@ -19,13 +18,12 @@ import {Platform} from '@angular/cdk/platform';
1918
textarea[mat-autosize], textarea[matTextareaAutosize]`,
2019
exportAs: 'mdTextareaAutosize',
2120
host: {
22-
'(input)': 'resizeToFitContent()',
2321
// Textarea elements that have the directive applied should have a single row by default.
2422
// Browsers normally show two rows by default and therefore this limits the minRows binding.
2523
'rows': '1',
2624
},
2725
})
28-
export class MdTextareaAutosize implements AfterViewInit {
26+
export class MdTextareaAutosize implements AfterViewInit, DoCheck {
2927
/** Keep track of the previous textarea value to avoid resizing when the value hasn't changed. */
3028
private _previousValue: string;
3129

@@ -58,15 +56,7 @@ export class MdTextareaAutosize implements AfterViewInit {
5856
/** Cached height of a textarea with a single row. */
5957
private _cachedLineHeight: number;
6058

61-
constructor(
62-
private _elementRef: ElementRef,
63-
private _platform: Platform,
64-
@Optional() @Self() formControl: NgControl) {
65-
66-
if (formControl && formControl.valueChanges) {
67-
formControl.valueChanges.subscribe(() => this.resizeToFitContent());
68-
}
69-
}
59+
constructor(private _elementRef: ElementRef, private _platform: Platform) {}
7060

7161
/** Sets the minimum height of the textarea as determined by minRows. */
7262
_setMinHeight(): void {
@@ -142,11 +132,17 @@ export class MdTextareaAutosize implements AfterViewInit {
142132
this._setMaxHeight();
143133
}
144134

135+
ngDoCheck() {
136+
this.resizeToFitContent();
137+
}
138+
145139
/** Resize the textarea to fit its content. */
146140
resizeToFitContent() {
147141
const textarea = this._elementRef.nativeElement as HTMLTextAreaElement;
142+
const value = textarea.value;
148143

149-
if (textarea.value === this._previousValue) {
144+
// Only resize of the value changed since these calculations can be expensive.
145+
if (value === this._previousValue) {
150146
return;
151147
}
152148

@@ -159,6 +155,6 @@ export class MdTextareaAutosize implements AfterViewInit {
159155
textarea.style.height = `${textarea.scrollHeight}px`;
160156
textarea.style.overflow = '';
161157

162-
this._previousValue = textarea.value;
158+
this._previousValue = value;
163159
}
164160
}

0 commit comments

Comments
 (0)