Material-ui: Other InputProps are not applied to InputProps.inputComponent

Created on 1 Aug 2018  ·  4Comments  ·  Source: mui-org/material-ui

  • [x] This is a v1.x issue.
  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

        <TextField
          className={classes.formControl}
          label="react-number-format"
          value={numberformat}
          onChange={this.handleChange("numberformat")}
          id="formatted-numberformat-input"
          InputProps={{
            inputComponent: NumberFormatCustom,
            testProp: "yo"
          }}
        />

The testProp should be passed along with other input properties when instantiating NumberFormatCustom: <NumberFormatCustom testProp="yo" ... />.

Current Behavior

The testProp is not passed.

Steps to Reproduce

Code to reproduce the issue: https://codesandbox.io/s/5z8xqoozzn

/* eslint-disable react/prefer-stateless-function */

import React from "react";
import NumberFormat from "react-number-format";
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";

const styles = theme => ({
  container: {
    display: "flex",
    flexWrap: "wrap"
  },
  formControl: {
    margin: theme.spacing.unit
  }
});

function NumberFormatCustom(props) {
  const { inputRef, onChange, testProp, ...other } = props;
  // THIS SHOULD BE "YO" but is undefined instead
  console.log("testProp", testProp);
  return (
    <NumberFormat
      {...other}
      ref={inputRef}
      onValueChange={values => {
        onChange({
          target: {
            value: values.value
          }
        });
      }}
      thousandSeparator
      prefix="$"
    />
  );
}

NumberFormatCustom.propTypes = {
  inputRef: PropTypes.func.isRequired,
  onChange: PropTypes.func.isRequired
};

class FormattedInputs extends React.Component {
  state = {
    textmask: "(1  )    -    ",
    numberformat: "1320"
  };

  handleChange = name => event => {
    this.setState({
      [name]: event.target.value
    });
  };

  render() {
    const { classes } = this.props;
    const { textmask, numberformat } = this.state;

    return (
      <div className={classes.container}>
        <TextField
          className={classes.formControl}
          label="react-number-format"
          value={numberformat}
          onChange={this.handleChange("numberformat")}
          id="formatted-numberformat-input"
          InputProps={{
            inputComponent: NumberFormatCustom,
            testProp: "yo"
          }}
        />
      </div>
    );
  }
}

FormattedInputs.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(FormattedInputs);

Context

There seems to be some discussion about TextField having too complex an API and targetting only 80% of the use cases, e.g. #9326. IMHO, the behavior looks like a bug (or I'm doing something wrong, because after reading the code the InputProps seem to be passed correctly.

Your Environment

| Tech | Version |
|--------------|---------|
| Material-UI | v1.4.2 |
| React | 16.4.1 |
| browser | N/A |

Most helpful comment

My bad, that's indeed the case, the proper way to do this is:

inputComponent: (props) => <NumberFormatCustom testProp="yo" {...props} />,

All 4 comments

Actually, re-reading https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Input/Input.js#L462-L469, it does look like only inputProps (the props meant to be applied to the DOM input element) are passed.

My bad, that's indeed the case, the proper way to do this is:

inputComponent: (props) => <NumberFormatCustom testProp="yo" {...props} />,

@charlax I tried doing like in your last post but it makes the input lose focus on each character typing. I am trying to propagate max prop down to NumberFormatCustom and this is what I get

Just in case someone will still be interested in this.

This way:
inputComponent: (props) => <NumberFormatCustom testProp="yo" {...props} />,

will cause input to loose focus on each keydown.

You might override it. Instead of passing an inline function, define the same function out of the scope of your component:

const NumberFormatCustomWithProps = props => <NumberFormatCustom testProp="yo" {...props} />,

class FormattedInputs extends React.Component {
   ...

   inputComponent: NumberFormatCustomWithProps,

   ...
}

In this case, props will be applied to input HTML element.


If what you want is just to pass properties down to the NumberFormatCustom, you may do the following (probably not an optimal way, but might be used as a workaround):

Wrap your component into another function. It will look like this (component should be function in this case):

const NumberFormatCustom = customProps => props => {

  // Both customProps & props are accessible here!
   ...

};

// Invoke the function first & then use it as needed.

const NumberFormatSetter = NumberFormatCustom({ myProp: "yo" });

class FormattedInputs extends React.Component {
   ...

   inputComponent: NumberFormatSetter,

   ...
}

Spoiler:
Both ways are quite ugly & play well only with static properties or if passed directly from parents.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

reflog picture reflog  ·  3Comments

ghost picture ghost  ·  3Comments

ryanflorence picture ryanflorence  ·  3Comments

newoga picture newoga  ·  3Comments

pola88 picture pola88  ·  3Comments