Select single option in SelectField redux-form-material-ui

492 views Asked by At

I have some forms in my redux app. I use redux-form-material-ui as well. I'd like SelectFields that have just one option to be set by default to that option. Is the only way to do this by setting initialValues while constructing the form component?

2

There are 2 answers

0
Paweł Koniarski On BEST ANSWER

The solution is really simple. You just have to follow the redux-form flow properly and call onChange defined by Field from redux-form.

import React from 'react';

import { SelectField as MUISelectField } from "redux-form-material-ui";

export class SelectField extends React.Component {
  constructor(props) {
    super(props);

    this.chooseSingleOption();
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevProps.children !== this.props.children) {
      this.chooseSingleOption();
    }
  }

  chooseSingleOption() {
    const children = React.Children.toArray(this.props.children);
    if (children.length === 1) {
      this.props.input.onChange(children[0].props.value);
    }
  }

  render() {
    return (
      <MUISelectField {...this.props}/>
    )
  }
}
0
jonahe On

Surprisingly the answer seems to be "No". At least it doesn't seem to be as easy as just passing a prop.

Material-ui (the original, not the Redux-form variation) doesn't support the defaultValue option for SelectField. I also found a similar thread for Redux-form.

You could probably still solve it if you always have the data for SelectField options in an array. Then you could maybe have function that turns that array into an array of MenuItems.

// example option data
const optionDataArray = [{ value: "first option", key: 0 }, { value: "second option", key: 1 }];
const toMenuItem = menuData =>
     (<MenuItem value={value} key={key} primaryText={ value } />)
  );

Then you could render them like

<SelectField value={ 
    optionDataArray.length === 1 ? 
       optionDataArray[0].value :
       null
 } >
  { optionDataArray.map(toMenuItem) } 
</SelectField>

I haven't tried this, but hopefully this makes the one-item SelectFields controlled components with pre-selected input. And I'm hoping the null value will interpreted as if we didn't provide anything at all.

But if the second assumption/hope isn't true, then you could perhaps make a function that like this:

const getSelectFieldValueProp = allOptionData => {
  if(allOptionData.length == 1) {
    return { value: allOptionData[0].value }
  } else {
    return {};
  }
}

And use it like

<SelectField {...getSelectFieldValueProp(optionDataArray) } >
  { optionDataArray.map(toMenuItem) } 
</SelectField>

That way only the one-item SelectFields should get the value prop set.