diff --git a/packages/material-ui/src/FormControl/FormControl.js b/packages/material-ui/src/FormControl/FormControl.js
index cb0d64548f5c82..3e94a6e66bc87e 100644
--- a/packages/material-ui/src/FormControl/FormControl.js
+++ b/packages/material-ui/src/FormControl/FormControl.js
@@ -48,6 +48,13 @@ export const styles = {
* ⚠️ Only one input can be used within a FormControl.
*/
class FormControl extends React.Component {
+ static getDerivedStateFromProps(props, state) {
+ if (props.disabled && state.focused) {
+ return { focused: false };
+ }
+ return null;
+ }
+
constructor(props) {
super();
diff --git a/packages/material-ui/src/FormControl/FormControl.test.js b/packages/material-ui/src/FormControl/FormControl.test.js
index 72854ca18d720b..fe2a86d9e4f6f7 100644
--- a/packages/material-ui/src/FormControl/FormControl.test.js
+++ b/packages/material-ui/src/FormControl/FormControl.test.js
@@ -78,6 +78,15 @@ describe('', () => {
});
});
+ describe('prop: disabled', () => {
+ it('will be unfocused if it gets disabled', () => {
+ const wrapper = shallow();
+ wrapper.setState({ focused: true });
+ wrapper.setProps({ disabled: true });
+ assert.strictEqual(wrapper.state().focused, false);
+ });
+ });
+
describe('input', () => {
it('should be filled with a value', () => {
const wrapper = shallow(
diff --git a/packages/material-ui/src/InputBase/InputBase.js b/packages/material-ui/src/InputBase/InputBase.js
index 1576da0f511391..d4ec58b612193b 100644
--- a/packages/material-ui/src/InputBase/InputBase.js
+++ b/packages/material-ui/src/InputBase/InputBase.js
@@ -154,47 +154,21 @@ export function formControlState({ props, states, context }) {
* It contains a load of style reset and some state logic.
*/
class InputBase extends React.Component {
+ static getDerivedStateFromProps(props, state) {
+ // The blur won't fire when the disabled state is set on a focused input.
+ // We need to book keep the focused state manually.
+ if (props.disabled && state.focused) {
+ return { focused: false };
+ }
+ return null;
+ }
+
constructor(props, context) {
super(props, context);
this.isControlled = props.value != null;
if (this.isControlled) {
this.checkDirty(props);
}
-
- const componentWillReceiveProps = (nextProps, nextContext) => {
- // The blur won't fire when the disabled state is set on a focused input.
- // We need to book keep the focused state manually.
- if (
- !formControlState({ props: this.props, context: this.context, states: ['disabled'] })
- .disabled &&
- formControlState({ props: nextProps, context: nextContext, states: ['disabled'] }).disabled
- ) {
- this.setState({
- focused: false,
- });
- }
- };
-
- const componentWillUpdate = (nextProps, nextState, nextContext) => {
- // Book keep the focused state.
- if (
- !formControlState({ props: this.props, context: this.context, states: ['disabled'] })
- .disabled &&
- formControlState({ props: nextProps, context: nextContext, states: ['disabled'] }).disabled
- ) {
- const { muiFormControl } = this.context;
- if (muiFormControl && muiFormControl.onBlur) {
- muiFormControl.onBlur();
- }
- }
- };
-
- /* eslint-disable no-underscore-dangle */
- this.componentWillReceiveProps = componentWillReceiveProps;
- this.componentWillReceiveProps.__suppressDeprecationWarning = true;
- this.componentWillUpdate = componentWillUpdate;
- this.componentWillUpdate.__suppressDeprecationWarning = true;
- /* eslint-enable no-underscore-dangle */
}
state = {
@@ -215,7 +189,14 @@ class InputBase extends React.Component {
}
}
- componentDidUpdate() {
+ componentDidUpdate(prevProps) {
+ // Book keep the focused state.
+ if (!prevProps.disabled && this.props.disabled) {
+ const { muiFormControl } = this.context;
+ if (muiFormControl && muiFormControl.onBlur) {
+ muiFormControl.onBlur();
+ }
+ }
if (this.isControlled) {
this.checkDirty(this.props);
} // else performed in the onChange
@@ -354,13 +335,15 @@ class InputBase extends React.Component {
states: ['disabled', 'error', 'margin', 'required', 'filled'],
});
+ const focused = muiFormControl ? muiFormControl.focused : this.state.focused;
+
const className = classNames(
classes.root,
{
[classes.disabled]: fcs.disabled,
[classes.error]: fcs.error,
[classes.fullWidth]: fullWidth,
- [classes.focused]: this.state.focused,
+ [classes.focused]: focused,
[classes.formControl]: muiFormControl,
[classes.marginDense]: fcs.margin === 'dense',
[classes.multiline]: multiline,
@@ -424,7 +407,7 @@ class InputBase extends React.Component {
? renderPrefix({
...fcs,
startAdornment,
- focused: this.state.focused,
+ focused,
})
: null}
{startAdornment}
diff --git a/packages/material-ui/src/InputBase/InputBase.test.js b/packages/material-ui/src/InputBase/InputBase.test.js
index dd35575b615b89..b0d969d08dfdf9 100644
--- a/packages/material-ui/src/InputBase/InputBase.test.js
+++ b/packages/material-ui/src/InputBase/InputBase.test.js
@@ -368,6 +368,18 @@ describe('', () => {
assert.strictEqual(input.props().required, true);
});
});
+
+ describe('focused', () => {
+ it('prioritizes context focus', () => {
+ wrapper.setState({ focused: true });
+
+ setFormControlContext({ focused: false });
+ assert.strictEqual(wrapper.hasClass(classes.focused), false);
+
+ setFormControlContext({ focused: true });
+ assert.strictEqual(wrapper.hasClass(classes.focused), true);
+ });
+ });
});
describe('componentDidMount', () => {