fix(autosize): resize when form value changes. Fixes #4657 (#5315)

This commit is contained in:
Jeremy Elbourn
2017-06-23 13:01:25 -07:00
committed by GitHub
parent 2361385dfc
commit 8c9c11a4b0
6 changed files with 706 additions and 740 deletions
+630 -723
View File
File diff suppressed because it is too large Load Diff
+12 -12
View File
@@ -25,13 +25,13 @@
"node": ">= 5.4.1 < 7"
},
"dependencies": {
"@angular/animations": "^4.0.0",
"@angular/common": "^4.0.0",
"@angular/compiler": "^4.0.0",
"@angular/core": "^4.0.0",
"@angular/forms": "^4.0.0",
"@angular/http": "^4.0.0",
"@angular/platform-browser": "^4.0.0",
"@angular/animations": "~4.1.0",
"@angular/common": "~4.1.0",
"@angular/compiler": "~4.1.0",
"@angular/core": "~4.1.0",
"@angular/forms": "~4.1.0",
"@angular/http": "~4.1.0",
"@angular/platform-browser": "~4.1.0",
"core-js": "^2.4.1",
"rxjs": "^5.0.1",
"systemjs": "0.19.43",
@@ -39,11 +39,11 @@
"zone.js": "^0.8.4"
},
"devDependencies": {
"@angular/compiler-cli": "^4.0.0",
"@angular/platform-browser-dynamic": "^4.0.0",
"@angular/platform-server": "^4.0.0",
"@angular/router": "^4.0.0",
"@angular/tsc-wrapped": "^4.0.0",
"@angular/compiler-cli": "~4.1.0",
"@angular/platform-browser-dynamic": "~4.1.0",
"@angular/platform-server": "~4.1.0",
"@angular/router": "~4.1.0",
"@angular/tsc-wrapped": "~4.1.0",
"@google-cloud/storage": "^1.1.1",
"@types/chalk": "^0.4.31",
"@types/fs-extra": "^3.0.1",
+12
View File
@@ -375,7 +375,10 @@
<md-card class="demo-card demo-basic">
<md-toolbar color="primary">Textarea Autosize</md-toolbar>
<md-card-content>
<h3>Regular &lt;textarea&gt;</h3>
<textarea mdTextareaAutosize class="demo-textarea"></textarea>
<h3>&lt;textarea&gt; with md-input-container</h3>
<div>
<md-input-container>
<textarea mdInput
@@ -383,5 +386,14 @@
placeholder="Autosized textarea"></textarea>
</md-input-container>
</div>
<h3>&lt;textarea&gt; with ngModel</h3>
<div>
<label>Input with same ngModel <input [(ngModel)]="textareaNgModelValue"></label>
</div>
<label>
Plain textarea with auto size
<textarea mdTextareaAutosize [(ngModel)]="textareaNgModelValue"></textarea>
</label>
</md-card-content>
</md-card>
+1
View File
@@ -18,6 +18,7 @@ export class InputDemo {
requiredField: boolean;
hideRequiredMarker: boolean;
ctrlDisabled = false;
textareaNgModelValue: string;
name: string;
errorMessageExample1: string;
+36 -3
View File
@@ -1,5 +1,6 @@
import {Component, ViewChild} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {FormsModule} from '@angular/forms';
import {ComponentFixture, TestBed, async, fakeAsync, flushMicrotasks} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {MdInputModule} from './index';
import {MdTextareaAutosize} from './autosize';
@@ -12,8 +13,12 @@ describe('MdTextareaAutosize', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MdInputModule],
declarations: [AutosizeTextAreaWithContent, AutosizeTextAreaWithValue],
imports: [MdInputModule, FormsModule],
declarations: [
AutosizeTextAreaWithContent,
AutosizeTextAreaWithValue,
AutosizeTextareaWithNgModel
],
});
TestBed.compileComponents();
@@ -145,6 +150,26 @@ describe('MdTextareaAutosize', () => {
.toBe(textarea.scrollHeight, 'Expected textarea height to match its scrollHeight');
});
it('should resize when an associated form control value changes', fakeAsync(() => {
const fixtureWithForms = TestBed.createComponent(AutosizeTextareaWithNgModel);
textarea = fixtureWithForms.nativeElement.querySelector('textarea');
fixtureWithForms.detectChanges();
const previousHeight = textarea.clientHeight;
fixtureWithForms.componentInstance.model = `
And the silken, sad, uncertain rustling of each purple curtain
Thrilled me—filled me with fantastic terrors never felt before;
So that now, to still the beating of my heart, I stood repeating
“’Tis some visitor entreating entrance at my chamber door—
Some late visitor entreating entrance at my chamber door;—
This it is and nothing more.” `;
fixtureWithForms.detectChanges();
flushMicrotasks();
expect(textarea.clientHeight)
.toBeGreaterThan(previousHeight, 'Expected increased height when ngModel is updated.');
}));
});
@@ -178,3 +203,11 @@ class AutosizeTextAreaWithContent {
class AutosizeTextAreaWithValue {
value: string = '';
}
@Component({
template: `<textarea mdTextareaAutosize [(ngModel)]="model"></textarea>`,
styles: [textareaStyleReset],
})
class AutosizeTextareaWithNgModel {
model = '';
}
+15 -2
View File
@@ -6,7 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Directive, ElementRef, Input, AfterViewInit} from '@angular/core';
import {Directive, ElementRef, Input, AfterViewInit, Optional, Self} from '@angular/core';
import {NgControl} from '@angular/forms';
/**
@@ -24,6 +25,9 @@ import {Directive, ElementRef, Input, AfterViewInit} from '@angular/core';
},
})
export class MdTextareaAutosize implements AfterViewInit {
/** Keep track of the previous textarea value to avoid resizing when the value hasn't changed. */
private _previousValue: string;
private _minRows: number;
private _maxRows: number;
@@ -53,7 +57,11 @@ export class MdTextareaAutosize implements AfterViewInit {
/** Cached height of a textarea with a single row. */
private _cachedLineHeight: number;
constructor(private _elementRef: ElementRef) { }
constructor(private _elementRef: ElementRef, @Optional() @Self() formControl: NgControl) {
if (formControl && formControl.valueChanges) {
formControl.valueChanges.subscribe(() => this.resizeToFitContent());
}
}
/** Sets the minimum height of the textarea as determined by minRows. */
_setMinHeight(): void {
@@ -123,11 +131,16 @@ export class MdTextareaAutosize implements AfterViewInit {
/** Resize the textarea to fit its content. */
resizeToFitContent() {
const textarea = this._elementRef.nativeElement as HTMLTextAreaElement;
if (textarea.value === this._previousValue) {
return;
}
// Reset the textarea height to auto in order to shrink back to its default size.
textarea.style.height = 'auto';
// Use the scrollHeight to know how large the textarea *would* be if fit its entire value.
textarea.style.height = `${textarea.scrollHeight}px`;
this._previousValue = textarea.value;
}
}