Skip to content

fix(text-field): unable to undo/redo in autosized text field on firefox #19238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions src/cdk/text-field/_text-field.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,28 @@
// removed when measuring is complete. We use `!important` rules here to make sure user-specified
// rules do not interfere with the measurement.
textarea.cdk-textarea-autosize-measuring {
@include _cdk-textarea-autosize-measuring-base;
height: auto !important;
overflow: hidden !important;
// Having 2px top and bottom padding seems to fix a bug where Chrome gets an incorrect
// measurement. We just have to account for it later and subtract it off the final result.
padding: 2px 0 !important;
box-sizing: content-box !important;
}

// Similar to the `cdk-textarea-autosize-measuring` class, but only applied on Firefox. We need
// to use this class, because Firefox has a bug where changing the `overflow` breaks the user's
// ability to undo/redo what they were typing (see #16629). This class is only scoped to Firefox,
// because the measurements there don't seem to be affected by the `height: 0`, whereas on other
// browsers they are, e.g. Chrome detects longer text and IE does't resize back to normal.
// Identical issue report: https://bugzilla.mozilla.org/show_bug.cgi?id=448784
textarea.cdk-textarea-autosize-measuring-firefox {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think overflow:hidden was there because it prevented scrollbars from messing up the calculation. Have you confirmed if this is a problem on firefox now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed to behave correctly when I was testing it out in the dev app. I was trying both the one that's on a plain textarea, as well as the one in the form field.

@include _cdk-textarea-autosize-measuring-base;
height: 0 !important;
}
}

@mixin _cdk-textarea-autosize-measuring-base {
// Having 2px top and bottom padding seems to fix a bug where Chrome gets an incorrect
// measurement. We just have to account for it later and subtract it off the final result.
padding: 2px 0 !important;
box-sizing: content-box !important;
}

// Used to generate UIDs for keyframes used to change the text field autofill styles.
Expand Down
14 changes: 10 additions & 4 deletions src/cdk/text-field/autosize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
/** Used to reference correct document/window */
protected _document?: Document;

/** Class that should be applied to the textarea while it's being measured. */
private _measuringClass: string;

constructor(private _elementRef: ElementRef<HTMLElement>,
private _platform: Platform,
private _ngZone: NgZone,
Expand All @@ -102,6 +105,9 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
this._document = document;

this._textareaElement = this._elementRef.nativeElement as HTMLTextAreaElement;
this._measuringClass = _platform.FIREFOX ?
'cdk-textarea-autosize-measuring-firefox' :
'cdk-textarea-autosize-measuring';
}

/** Sets the minimum height of the textarea as determined by minRows. */
Expand Down Expand Up @@ -229,16 +235,16 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
// 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('cdk-textarea-autosize-measuring');
textarea.classList.add(this._measuringClass);
textarea.placeholder = '';

// The cdk-textarea-autosize-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).
// 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 = 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('cdk-textarea-autosize-measuring');
textarea.classList.remove(this._measuringClass);
textarea.placeholder = placeholderText;

this._ngZone.runOutsideAngular(() => {
Expand Down