Skip to content

Commit

Permalink
Revert "fix(cdk/text-field): autosize text areas using the placeholder (
Browse files Browse the repository at this point in the history
#22197)" (#22296)

This reverts commit 476a90b.
  • Loading branch information
andrewseguin authored Mar 19, 2021
1 parent 2e1214f commit 4316787
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 103 deletions.
2 changes: 1 addition & 1 deletion scripts/check-mdc-tests-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const config = {
'should calculate the outline gaps inside the shadow DOM',
'should be legacy appearance if no default options provided',
'should be legacy appearance if empty default options provided',
'should adjust height due to long placeholders',
'should not calculate wrong content height due to long placeholders',
'should work in a tab',
'should work in a step'
],
Expand Down
62 changes: 4 additions & 58 deletions src/cdk/text-field/autosize.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ describe('CdkTextareaAutosize', () => {
it('should resize the textarea based on its content', () => {
let previousHeight = textarea.clientHeight;

textarea.value = `
fixture.componentInstance.content = `
Once upon a midnight dreary, while I pondered, weak and weary,
Over many a quaint and curious volume of forgotten lore—
While I nodded, nearly napping, suddenly there came a tapping,
Expand All @@ -68,7 +68,7 @@ describe('CdkTextareaAutosize', () => {
.toBe(textarea.scrollHeight, 'Expected textarea height to match its scrollHeight');

previousHeight = textarea.clientHeight;
textarea.value += `
fixture.componentInstance.content += `
Ah, distinctly I remember it was in the bleak December;
And each separate dying ember wrought its ghost upon the floor.
Eagerly I wished the morrow;—vainly I had sought to borrow
Expand All @@ -85,38 +85,6 @@ describe('CdkTextareaAutosize', () => {
.toBe(textarea.scrollHeight, 'Expected textarea height to match its scrollHeight');
});

it('should keep the placeholder size if the value is shorter than the placeholder', () => {
fixture = TestBed.createComponent(AutosizeTextAreaWithContent);

textarea = fixture.nativeElement.querySelector('textarea');
autosize = fixture.debugElement.query(By.css('textarea'))!
.injector.get<CdkTextareaAutosize>(CdkTextareaAutosize);

fixture.componentInstance.placeholder = `
Once upon a midnight dreary, while I pondered, weak and weary,
Over many a quaint and curious volume of forgotten lore—
While I nodded, nearly napping, suddenly there came a tapping,
As of some one gently rapping, rapping at my chamber door.
“’Tis some visitor,” I muttered, “tapping at my chamber door—
Only this and nothing more.”`;

fixture.detectChanges();

expect(textarea.clientHeight)
.toBe(textarea.scrollHeight, 'Expected textarea height to match its scrollHeight');

let previousHeight = textarea.clientHeight;

textarea.value = 'a';

// Manually call resizeToFitContent instead of faking an `input` event.
fixture.detectChanges();
autosize.resizeToFitContent();

expect(textarea.clientHeight)
.toBe(previousHeight, 'Expected textarea height not to have changed');
});

it('should set a min-height based on minRows', () => {
expect(textarea.style.minHeight).toBeFalsy();

Expand Down Expand Up @@ -193,7 +161,7 @@ describe('CdkTextareaAutosize', () => {
});

it('should calculate the proper height based on the specified amount of max rows', () => {
textarea.value = [1, 2, 3, 4, 5, 6, 7, 8].join('\n');
fixture.componentInstance.content = [1, 2, 3, 4, 5, 6, 7, 8].join('\n');
fixture.detectChanges();
autosize.resizeToFitContent();

Expand Down Expand Up @@ -228,27 +196,6 @@ describe('CdkTextareaAutosize', () => {
.toBe(textarea.scrollHeight, 'Expected textarea height to match its scrollHeight');
});

it('should properly resize to placeholder on init', () => {
// Manually create the test component in this test, because in this test the first change
// detection should be triggered after a multiline placeholder is set.
fixture = TestBed.createComponent(AutosizeTextAreaWithContent);
textarea = fixture.nativeElement.querySelector('textarea');
autosize = fixture.debugElement.query(By.css('textarea'))!
.injector.get<CdkTextareaAutosize>(CdkTextareaAutosize);

fixture.componentInstance.placeholder = `
Line
Line
Line
Line
Line`;

fixture.detectChanges();

expect(textarea.clientHeight)
.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');
Expand Down Expand Up @@ -351,15 +298,14 @@ const textareaStyleReset = `
@Component({
template: `
<textarea cdkTextareaAutosize [cdkAutosizeMinRows]="minRows" [cdkAutosizeMaxRows]="maxRows"
#autosize="cdkTextareaAutosize" [placeholder]="placeholder">{{content}}</textarea>`,
#autosize="cdkTextareaAutosize">{{content}}</textarea>`,
styles: [textareaStyleReset],
})
class AutosizeTextAreaWithContent {
@ViewChild('autosize') autosize: CdkTextareaAutosize;
minRows: number | null = null;
maxRows: number | null = null;
content: string = '';
placeholder: string = '';
}

@Component({
Expand Down
50 changes: 12 additions & 38 deletions src/cdk/text-field/autosize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,8 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
}
}

@Input()
get placeholder(): string { return this._textareaElement.placeholder; }
set placeholder(value: string) {
this._cachedPlaceholderHeight = undefined;
this._textareaElement.placeholder = value;
this._cacheTextareaPlaceholderHeight();
}


/** Cached height of a textarea with a single row. */
private _cachedLineHeight: number;
/** Cached height of a textarea with only the placeholder. */
private _cachedPlaceholderHeight?: number;

/** Used to reference correct document/window */
protected _document?: Document;
Expand Down Expand Up @@ -206,30 +195,6 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
this._setMaxHeight();
}

private _measureScrollHeight(): number {
// Reset the textarea height to auto in order to shrink back to its default size.
// Also temporarily force overflow:hidden, so scroll bars do not interfere with calculations.
this._textareaElement.classList.add(this._measuringClass);
// The measuring class includes a 2px padding to workaround an issue with Chrome,
// so we account for that extra space here by subtracting 4 (2px top + 2px bottom).
const scrollHeight = this._textareaElement.scrollHeight - 4;
this._textareaElement.classList.remove(this._measuringClass);

return scrollHeight;
}

private _cacheTextareaPlaceholderHeight(): void {
if (this._cachedPlaceholderHeight) {
return;
}

const value = this._textareaElement.value;

this._textareaElement.value = this._textareaElement.placeholder;
this._cachedPlaceholderHeight = this._measureScrollHeight();
this._textareaElement.value = value;
}

ngDoCheck() {
if (this._platform.isBrowser) {
this.resizeToFitContent();
Expand All @@ -248,7 +213,6 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
}

this._cacheTextareaLineHeight();
this._cacheTextareaPlaceholderHeight();

// If we haven't determined the line-height yet, we know we're still hidden and there's no point
// in checking the height of the textarea.
Expand All @@ -264,14 +228,24 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
return;
}

const scrollHeight = this._measureScrollHeight();
const placeholderText = textarea.placeholder;

// Reset the textarea height to auto in order to shrink back to its default size.
// Also temporarily force overflow:hidden, so scroll bars do not interfere with calculations.
// Long placeholders that are wider than the textarea width may lead to a bigger scrollHeight
// value. To ensure that the scrollHeight is not bigger than the content, the placeholders
// need to be removed temporarily.
textarea.classList.add(this._measuringClass);
textarea.placeholder = '';

// The measuring class includes a 2px padding to workaround an issue with Chrome,
// so we account for that extra space here by subtracting 4 (2px top + 2px bottom).
const height = Math.max(scrollHeight, this._cachedPlaceholderHeight || 0);
const height = textarea.scrollHeight - 4;

// Use the scrollHeight to know how large the textarea *would* be if fit its entire value.
textarea.style.height = `${height}px`;
textarea.classList.remove(this._measuringClass);
textarea.placeholder = placeholderText;

this._ngZone.runOutsideAngular(() => {
if (typeof requestAnimationFrame !== 'undefined') {
Expand Down
6 changes: 3 additions & 3 deletions src/material/input/input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1719,7 +1719,7 @@ describe('MatFormField default options', () => {
});

describe('MatInput with textarea autosize', () => {
it('should adjust height due to long placeholders', () => {
it('should not calculate wrong content height due to long placeholders', () => {
const fixture = createComponent(AutosizeTextareaWithLongPlaceholder);
fixture.detectChanges();

Expand All @@ -1735,8 +1735,8 @@ describe('MatInput with textarea autosize', () => {

autosize.resizeToFitContent(true);

expect(textarea.clientHeight).toBeLessThan(heightWithLongPlaceholder,
'Expected the textarea height to be shorter with a long placeholder.');
expect(textarea.clientHeight).toBe(heightWithLongPlaceholder,
'Expected the textarea height to be the same with a long placeholder.');
});

it('should work in a tab', () => {
Expand Down
4 changes: 1 addition & 3 deletions tools/public_api_guard/cdk/text-field.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ export declare class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDe
set maxRows(value: number);
get minRows(): number;
set minRows(value: number);
get placeholder(): string;
set placeholder(value: string);
constructor(_elementRef: ElementRef<HTMLElement>, _platform: Platform, _ngZone: NgZone,
document?: any);
_noopInputHandler(): void;
Expand All @@ -46,7 +44,7 @@ export declare class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDe
static ngAcceptInputType_enabled: BooleanInput;
static ngAcceptInputType_maxRows: NumberInput;
static ngAcceptInputType_minRows: NumberInput;
static ɵdir: i0.ɵɵDirectiveDefWithMeta<CdkTextareaAutosize, "textarea[cdkTextareaAutosize]", ["cdkTextareaAutosize"], { "minRows": "cdkAutosizeMinRows"; "maxRows": "cdkAutosizeMaxRows"; "enabled": "cdkTextareaAutosize"; "placeholder": "placeholder"; }, {}, never>;
static ɵdir: i0.ɵɵDirectiveDefWithMeta<CdkTextareaAutosize, "textarea[cdkTextareaAutosize]", ["cdkTextareaAutosize"], { "minRows": "cdkAutosizeMinRows"; "maxRows": "cdkAutosizeMaxRows"; "enabled": "cdkTextareaAutosize"; }, {}, never>;
static ɵfac: i0.ɵɵFactoryDef<CdkTextareaAutosize, [null, null, null, { optional: true; }]>;
}

Expand Down

0 comments on commit 4316787

Please sign in to comment.