Get the input html tag under select
Get only an object with value field
Try to render MySelect from
const setData = (e) => console.log(e.target)
export const MySelect = () => (
<FormControl fullWidth>
<InputLabel htmlFor="age-simple">Civilit茅</InputLabel>
<Select
value={'Monsieur'}
onChange={setData}
input={<Input />}
label={'Civilit茅'}
name='civility'
>
<MenuItem value={'Mr'}>Monsieur</MenuItem>
<MenuItem value={'Mme'}>Madame</MenuItem>
</Select>
</FormControl>
)
I need to get the name field of my Select
However this one is not present in the triggered event
Ubuntu 17.04 (64bit)
| Tech | Version |
|--------------|---------|
| Material-UI | 1.0.0-beta.12 |
| React | 15.6.1 |
| browser | Chrome 61.0.3163.100 (64bit) |
| node | 8.1.4 |
| npm | 5.4.2聽|
| create-react-app聽| 1.4.0聽|
How about reproducing with the codesandbox link than was in the issue template?
@rosskevin This time, the provided information is enough to look into the issue.
I need to get the name field of my Select
However this one is not present in the triggered event
@robininfo-edsx The event is coming from a click/key interaction as you can find in:
https://github.com/callemall/material-ui/blob/6918de85cc2fc5a05ae400cc21f4d4319eae195a/src/Select/SelectInput.js#L149
You won't be able to access the hidden input field this way. This is not something we want to support. But then, I don't understand the use case as you are the one providing a name to the input.
Anyway, you can use the inputRef
property on the <Input />
to get access the native hidden input field.
P.S. With the native version of the Select component, you can use the event to access the native select input field.
I do as React documentation does because if you use something like this
const setData = (name) => (e) => console.log(e.target)
export const MySelect = () => (
<FormControl fullWidth>
<InputLabel htmlFor="age-simple">Civilit茅</InputLabel>
<Select
value={'Monsieur'}
onChange={setData(civility)}
input={<Input />}
label={'Civilit茅'}
>
<MenuItem value={'Mr'}>Monsieur</MenuItem>
<MenuItem value={'Mme'}>Madame</MenuItem>
</Select>
</FormControl>
)
You create a function each time you rerender this Component, so using a depth 1 shallow comparison will return you to rerender each time.
I know that this not really usefull as actually material-ui components are rerender each time as when you rerender a child even with same same props, the props object is never the same wich cause a rerender of each material-ui components when you rerender the parent component.
The problem is actually that onChange event took 22ms to rerender my form, so it look like less reactive to user input.
I've been using the Formik library recently https://github.com/jaredpalmer/formik and it throws this warning:
Warning: You forgot to pass an `id` or `name` attribute to your input
Since event.target
has no name
or id
, Formik can't figure out what input in the form changed. It works fine using <Select native>
though.
Unless I'm missing something, using native selects is the only way around this?
@mgrijalva You are right. Formik uses the following logic. I'm curious about the integration with other form libraries. Still, you have an alternative on userland, you can write an adapter between Material-UI onChange
output and Formik
requirements. It's simple.
I'm adding the waiting for user feedback
label. We might be able to implement something better on our side, but without more feedback, it's hard to tell. So please, people raised your voice if you encounter a similar situation.
So far we have:
onChange.event.target.name
.I have been looking at what Ant Design is doing with their custom select. They don't even expose the event
(using rc-select internally). So the situation is worth on their end. I couldn't find any other benchmark. I think that we can keep the issue closed until further use cases is discovered.
@oliviertassinari I am struggling through Formik issues as well. When you say:
you can write an adapter between Material-UI onChange output and Formik requirements. It's simple.
What would an adapter look like in this scenario?
I just started playing with formik using material-ui components today. so far, it seems like you may need to write some wrapper components to integrate formik Field
with MU components similar to the React Native related documentation on Formik's readme.
e.g., using render property on formik Field
, you can pass a component that uses MU TextField
and bind TextField.value
to props.field.value
and TextField.onChange
to (event, newValue) => props.form.setFieldValue('someFormFieldName', newValue)
.
not sure if the most elegant way, but seems to be working.
oh, i saw that you can manipulate input.name
via TextField.name
property, so you can actually do TextField.onChange
as props.form.handleChange
if you set TextField.name
properly. If you need to get the initial value, you also need to have TextField.value
binding.
Hi @burcakulug, have you a running example of a solution that I could use for my project ? I struggle with this warning :-(
Hi @jfperrin , I have started this personal fun project, you can take a look at this as a sample.
https://github.com/burcakulug/mytvguide/blob/master/app/containers/UsersPage/index.js#L36
For my actual work project, I implemented some wrapper components using Formik's Field and Material UI components, if that project gets opensource, I can also post it here later. For now, the one above should give you the gist.
Hi, i'm also struggling with this warning when using Formik with the Material-ui SelectField. So i think it is enough for the devs to implement something better to resolve this issue.
i think a library wrapping mui components and bridging formik field to them would be good. that's what i sort of did for work, if i can manage, i may try to create a library for it.
I'm having the same issue.
I wrapped this for our team - it only took a few minutes.
If no one else creates a lib for it, I wouldn't mind sharing.
Here's an example for the TextField component:
import React from "react";
import PropTypes from "prop-types";
import { TextField } from "material-ui";
const MaterialInput = ({
field,
form: { touched, errors },
label,
...props
}) => (
<TextField
{...props}
{...field}
value={field.value || ""}
error={Boolean(touched[field.name] && errors[field.name])}
label={(touched[field.name] && errors[field.name]) || label}
/>
);
MaterialInput.propTypes = {
field: PropTypes.shape({
name: PropTypes.string,
value: PropTypes.any,
onChange: PropTypes.func,
onBlur: PropTypes.func
}).isRequired,
form: PropTypes.shape({
touched: PropTypes.object,
errors: PropTypes.object
// the rest of the formik bag too
}).isRequired,
label: PropTypes.string.isRequired
};
export default MaterialInput;
Here's an example with Selects:
import React from "react";
import PropTypes from "prop-types";
import { TextField } from "material-ui";
const MaterialInputSelect = ({
field,
form: { touched, errors },
label,
options,
...props
}) => (
<TextField
{...props}
{...field}
value={field.value || ""}
error={Boolean(touched[field.name] && errors[field.name])}
label={(touched[field.name] && errors[field.name]) || label}
select
SelectProps={{ native: true }}
>
<option value="">Select</option>
{options.map(option => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</TextField>
);
MaterialInputSelect.propTypes = {
field: PropTypes.shape({
name: PropTypes.string,
value: PropTypes.any,
onChange: PropTypes.func,
onBlur: PropTypes.func
}).isRequired,
form: PropTypes.shape({
touched: PropTypes.object,
errors: PropTypes.object
// the rest of the formik bag too
}).isRequired,
label: PropTypes.string.isRequired,
options: PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.any,
label: PropTypes.string
})
)
};
MaterialInputSelect.defaultProps = {
options: []
};
export default MaterialInputSelect;
And here's an example with Switches:
import React from "react";
import PropTypes from "prop-types";
import { FormControlLabel, Switch } from "material-ui";
const MaterialInput = ({
field: { value, ...field },
form,
label,
...props
}) => (
<FormControlLabel
control={<Switch {...field} {...props} checked={value || false} />}
label={label}
/>
);
MaterialInput.propTypes = {
field: PropTypes.shape({
name: PropTypes.string,
value: PropTypes.any,
onChange: PropTypes.func,
onBlur: PropTypes.func
}).isRequired,
form: PropTypes.shape({
// the formik bag
}).isRequired,
label: PropTypes.string.isRequired
};
export default MaterialInput;
Chiming in late for anyone also struggling with this, since I'm using MUI with Formik as well, but wanted the non-native Select. It seems you can achieve it by passing an ID down to the visible element that matches the form field name, like so:
<TextField
name="mySelectField"
label="Select something ..."
select
required
value={values.mySelectField}
SelectProps={{
SelectDisplayProps: {
id: 'mySelectField'
}
}}
onChange={handleChange}
onBlur={handleBlur}
>
{mySelectOptions.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
FYI, this last snippet seems like MUI v1.x
0.x versions would similar to the previous snippets.
Most helpful comment
Here's an example for the TextField component:
Here's an example with Selects:
And here's an example with Switches: