-
Notifications
You must be signed in to change notification settings - Fork 47.6k
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
Issue #11827 Fix ShadowDOM input bug with setDefaultValue #11986
Conversation
…when setting defaultValue
Generally this sort of thing is "tested" via a manual fixture. Check out fixtures/dom from the repo root for some existing ones and you can add one there. There is no automation, so don't be confused if you can't run them via a cli or something :P |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Just need to verify manually
let activeElement = node.ownerDocument.activeElement; | ||
|
||
if (activeElement && activeElement.shadowRoot) { | ||
activeElement = getShadowElementRoot(node.ownerDocument.activeElement); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh. Nice!
@chrisdieckhaus looks like you need to run |
Added manual test case to |
The field should read "3.", preserving the decimal place | ||
</TestCase.ExpectedResult> | ||
|
||
<NumberTestCase /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The formatting is perfect here, but it doesn't look like this attaches to a Shadow DOM. What is the best way to do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m not entirely sure how to deal with a Shadow DOM in the test fixtures. I’ll look into it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Marking this as "request changes" for the issues list.
Hi @nhunzaker is this good to merge? |
attachShadowDomElement(hostElementId, stringHtmlElement) { | ||
var hostElement = document.querySelector(hostElementId); | ||
var shadow = hostElement.attachShadow({mode: 'open'}); | ||
shadow.innerHTML = stringHtmlElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this injects<input type="number" value={this.state.value} onChange={this.onChange} />
, which is the form React requires, however this won't wire on onChange
, just set an HTML string uncontrolled by React. This will create a false positive for the bug because React doesn't interact with this injected markup.
We need to render a React component inside of a shadow dom sub-tree. It looks like #11827 includes a reproduction that does just this:
https://jsfiddle.net/69z2wepo/94566/
Drawing from that example, you could do:
import NumberTestCase from './NumberTestCase';
export default class NumberTestCaseShadowDOM extends React.Component {
componentWillMount() {
// I tucked the definition in here because I wasn't sure what extending HTMLElement
// would do in IE9. Maybe this isn't necessary.
class ShadowNumberInput extends HTMLElement {
connectedCallback(){
ReactDOM.render(<NumberTestCase />, this.attachShadow({ mode: 'open' }));
}
}
customElements.define('with-shadow-dom', ShadowNumberInput);
}
render() {
return (<shadow-number-input {...this.props} />);
}
}
Here's a working example: https://jsfiddle.net/2n77ootd/2/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So whenever I go with that sort of an implementation, I get the following error when it tries to render the shadow element:
TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
It seems like custom elements are not compatible with ES5 style classes. I'm able to get it working with their suggested solution, native-shim.js. Is this something we'd be able to include in react? Or should we be looking for a different solution to this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nhunzaker thoughts on this?
@chrisdieckhaus Sorry, not quite yet. The test case needs to render React inside of a shadow dom root. Like use ReactDOM.render inside of a Shadow DOM to verify that it coordinates properly with the parent DOM (Sunny DOM 😛?). I left some thoughts. Essentially I think we just need to render the same number input test case inside of a Shadow DOM, then mount an associated custom element with React (inside of the render method of the fixture component). |
Ah yeah I see what you mean. I'll play around with it and see what I can come up with. |
@nhunzaker, I added the native-shim.js file I mentioned earlier. I'm not sure if it's something that's acceptable to add, though. Take a look at it when you get a chance. |
Hey! Awesome. I'm out of pocket for a bit, but I'll look at this first thing in Monday (traveling). Thank you for sticking with me! |
Ah this is interesting. Custom Elements are not supposed (yet) in Firefox, which prevents the Number Input test case page from rendering. |
@chrisdieckhaus Hmm. We probably need to do a compatibility check. I think it would be fine if the fixture said something like "This browser does not support custom elements, this fixture is invalid". I apologize for getting back to this as late as I have. If you'd like me to pick this up, I'd be happy to carry this through. |
Would #11896 also fix this? |
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution. |
Closing this pull request after a prolonged period of inactivity. If this issue is still present in the latest release, please ask for this pull request to be reopened. Thank you! |
Fixes Issue #11827.
#7253 successfully fixed the number input backspace bug with removing decimals by not re-setting the default value if
node === activeElement
. However, shadowDOM elements are wrapped in a shadowRoot element, so comparing them tonode
always triggered an update tonode.defaultValue
(which triggeredinput
's validation that removed the decimal point). I've updatedsetDefaultState
to check for shadow DOM element, and if so, iterate to the rootactiveElement
to compare against node.I haven't added tests yet because I need some input on that. I'm assuming the tests should go in
ReactDOMInput-test.js
. However, I'm not sure how to properly mock a shadow DOM element in these tests, and would appreciate some input on that.