palantir/blueprint
在 GitHub 查看Multiline EditableText doesn't update height properly if changing controlled value on confirm
Open
#2,153 建立於 2018年2月19日
P3Package: coreType: bughelp wanted
描述
Bug report
- Package version(s): 1.35.4
- Browser and OS versions: Chrome 64.0.3282.167, OS X 10.12.6
Steps to reproduce
- Create an
EditableTextwith a controlledvalueandmultiline={true} - Add some validation logic in a parent component that, e.g., resets an empty value to the last saved value
onConfirm.
Actual behavior
(Going off the scenario above): The EditableText doesn't update its height to fit the newly updated value. It remains at one line tall, and the text overflows visually as in https://github.com/palantir/blueprint/issues/1610.
Likewise, e.g. if validation logic exists that reverts a 3-line value to a previously saved 1-line value onConfirm, then the EditableText erroneously remains 3 lines tall.
Expected behavior
The EditableText updates its height properly within componentWillReceiveProps.
--
Current workaround is to put something like the following in the parent component (note: this workaround is imperfect; it doesn't handle the case when the EditableText needs to shrink):
public componentDidUpdate() {
// Blueprint's EditableText doesn't adjust its height if the number of lines changes upon changing the
// controlled value. So we have to manage that ourselves for now. The two setTimeouts work as follows:
// 1. Delay to the end of *this* frame.
// 2. Delay to the end of the *next* frame.
// Both are necessary to ensure that EditableText's children finish repainting and resizing on blur before
// we measure here.
setTimeout(() => {
setTimeout(() => {
this.updateHeight();
});
});
}
private updateHeight() {
if (this.editableTextRef == null) {
return;
}
const parentElement = ReactDOM.findDOMNode(this.editableTextRef) as HTMLElement;
// Blueprint's EditableText doesn't expose a ref prop for this child, so we have to grab it via DOM APIs. Note
// that we need to query for the -content and not the -input, because this function will be executed only after
// leaving edit mode.
const childElement = parentElement.querySelector(".pt-editable-content") as HTMLElement;
if (childElement == null) {
return;
}
const inputHeight = childElement.style.height;
if (parentElement.style.height !== inputHeight) {
parentElement.style.height = inputHeight;
}
}