I'm trying to access input data using React's "ref" attribute on a TextField in Material-UI. There doesn't seem to be an easy way of doing this via the 'inputRef' or 'inputProps'.
The below sample shows the use of inputProps on line 26. Assigning the name of the TextField to the 'ref' property does not appear to produce a valid object.
With the “inputRef”, which according the Material-ui docs forces the use of a function, attempting to pass the field data in as an attribute also doesn't work. Ex: (txt => this.name = txt)
Has anyone found a solution?
class MediaForm extends Component {
constructor (props) {
super(props)
this.state = {}
this.handleSubmit = this.handleSubmit.bind(this)
}
handleSubmit (e) {
const { title, colour } = this.refs
e.preventDefault()
window.alert(`New colour: ${title.value} ${colour.value}`)
}
render () {
const { classes } = this.props
return (
<form className={classes.root}
onSubmit={this.handleSubmit}>
<div className={classes.field}>
<TextField
name='title'
type='text'
label='Title'
placeholder='Movie title...'
autoFocus
inputProps={{ref: this.name}}
required />
</div>
<div className={classes.field}>
<Tooltip title='Add a colour the reflects the mood of the film'>
<TextField
name='colour'
type='color'
label='Mood'
inputProps={{ref: this.name}}
required />
</Tooltip>
</div>
<Button
variant='raised'
color='primary'
className={classes.button}>
ADD
</Button>
</form>
)
}
}
MediaForm.propTypes = {
classes: PropTypes.object.isRequired
}
export default withRoot(withStyles(styles)(MediaForm))
The ref attribute makes it possible to store a reference to a particular React element or component returned by the component render() configuration function. This can be valuable when you need a reference, from within a component, to some element or component contained within the render() function.
We can use TextField component in Material UI to show input textbox. import TextField from "@material-ui/core/TextField"; When using the TextField component, we can pass the required attribute to mark the component as required.
Material UI is one of the popular React UI frameworks. Let us learn how to use material UI library in this chapter. Material UI can be installed using npm package. Material UI recommends roboto fonts for UI.
Refs are created using React.createRef() and attached to React elements via the ref attribute. Refs are commonly assigned to an instance property when a component is constructed so they can be referenced throughout the component.
How a conversation between a child component and an element containing the ref might go down. This is a component that renders some text, an input field, and a button. The ref is created in the constructor and then attached to the input element when it renders.
Using the components is simple. Just import the component from the library and render it like any other React component. The nice thing about the components is that they all contain their own styles, so there isn't a global CSS file that you have to worry about.
You do not need refs for that. The submit event contains the form as the target. You can access the inputs in a form via form.elements
:
handleSubmit (event) {
const { title, colour } = event.currentTarget.elements;
event.preventDefault();
window.alert(`New colour: ${title.value} ${colour.value}`);
}
To the problem with your refs: What does this.name
refer to? You did not declare it anywhere so it is undefined
. Passing undefined
to the ref
prop has no effect. Also how should it be possible to have two input refs being bound to the same instance property name
. Are you aware that the this
in your render function refers to the instance of your MediaForm
component and therefore this.name
is a property name
on your component instance (which is undefined)?
If you want to obtain the individual refs for each input you should use the callback pattern. Note that String refs are deprecated and should not be used:
render() {
return(
<TextField
name='title'
type='text'
label='Title'
placeholder='Movie title...'
autoFocus
inputProps={{ref: input => this.titleInput = input}}
required
/>
);
}
EDIT:
What you probably want is known as controlled component. In this pattern your parent component keeps track of the values of it's children (often inputs):
class MediaForm extends Component {
constructor(props) {
super(props);
this.state = {
title: '',
colour: '',
};
}
handleChange = event => {
const {name, value} = event.currentTarget;
this.setState({[name]: value});
};
handleSubmit = event => {
event.preventDefault();
const {title, colour} = this.state;
window.alert(`New colour: ${title} ${colour}`);
};
render() {
const {classes} = this.props;
const {title, colour} = this.state;
return (
<form className={classes.root} onSubmit={this.handleSubmit}>
<div className={classes.field}>
<TextField
name="title"
type="text"
value={title}
onChange={this.handleChange}
label="Title"
placeholder="Movie title..."
required
/>
</div>
<div className={classes.field}>
<Tooltip title="Add a colour the reflects the mood of the film">
<TextField
name="colour"
type="color"
value={colour}
onChange={this.handleChange}
label="Mood"
required
/>
</Tooltip>
</div>
<Button
type="submit"
variant="raised"
color="primary"
className={classes.button}
>
ADD
</Button>
</form>
);
}
}
Now your parent has full control and access over the value of each input via this.state.title
and this.state.colour
. Also no need for any ref here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With