问题
I have a situation where I need to show grouped lists of items: https://v0.material-ui.com/#/components/list (Go to Nested Lists)
Can redux-form Select field work with options as
<ListItem />
instead of<MenuItem />
?I can't select any item from the nested dropdown. Redux's
onChange
callback doesn't fire up.
Here is the code: Form:
<form>
<Field
name="camops"
normalize={normalizeMultipleSelectValues}
component={MySelectFormField}
floatingLabelText="Item(s)"
fullWidth
multiple
/>
</form>
Component MySelectFormField
:
import get from 'lodash/get';
import groupBy from 'lodash/groupBy';
import isEmpty from 'lodash/isEmpty';
import { List, ListItem } from 'material-ui/List';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Typography from '@material-ui/core/Typography';
import SelectFormField from './common/SelectFormField';
class MySelectFormField extends Component {
static propTypes = {
bookingId: PropTypes.string,
multiple: PropTypes.bool,
disabled: PropTypes.bool,
input: PropTypes.object.isRequired,
camops: PropTypes.array,
camopsFetch: PropTypes.func.isRequired,
};
static defaultProps = {
bookingId: null,
multiple: false,
disabled: false,
camops: [],
};
componentDidMount() {
const { camopsFetch } = this.props;
camopsFetch();
}
renderListItems(data) {
let listItems = null;
if (!isEmpty(data)) {
listItems = Object.keys(data).map(region => {
const count = data[region].length;
const nestedItems = this.renderNestedListItem(data[region]);
const primaryText = (
<Typography variant="h6" component="div">
{`${region}(${count})`}
</Typography>
);
return (
<ListItem
key={region}
primaryText={primaryText}
initiallyOpen={true}
primaryTogglesNestedList={true}
nestedItems={nestedItems}
/>
);
});
}
return listItems;
}
renderNestedListItem(data) {
let nestedList = null;
if (!isEmpty(data)) {
nestedList = data.map(camop => {
const uuid = get(camop, 'uuid', '');
const fullName = get(camop, 'full_name', '');
const email = get(camop, 'email', '');
const label = `${fullName} (${email})`.trim();
let checked = false;
if (this.props.multiple) {
checked = this.props.input.value.indexOf(uuid) > -1;
}
return <ListItem key={uuid} value={uuid} primaryText={label} checked={checked} />;
});
}
return nestedList;
}
render() {
const { bookingId, disabled, camops, camopsFetch, ...restProps } = this.props;
const hasCamOps = !!camops && !!camops.length;
const enabled = !disabled && hasCamOps;
let groupedCamops = groupBy(camops, 'region');
// Sort the grouped camops
groupedCamops = Object.keys(groupedCamops)
.sort()
.reduce((r, k) => Object.assign(r, { [k]: groupedCamops[k] }), {});
const listItems = this.renderListItems(groupedCamops);
return (
<SelectFormField {...restProps} disabled={!enabled}>
<List style={{ maxHeight: '100%', overflow: 'auto' }}>{listItems}</List>
</SelectFormField>
);
}
}
export default MySelectFormField;
Component SelectFormField
:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { SelectField } from 'redux-form-material-ui';
class SelectFormField extends Component {
static propTypes = {
children: PropTypes.node,
helpText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
meta: PropTypes.object.isRequired,
input: PropTypes.object.isRequired,
isRequired: PropTypes.bool,
};
static defaultProps = {
children: null,
helpText: null,
isRequired: false,
};
render() {
const { children, helpText, isRequired, ...restProps } = this.props;
return (
<div className="select-form-field">
<SelectField {...restProps}>{children}</SelectField>
{!!isRequired && <span className="select-form-field__marker">* </span>}
{!!helpText && <div className="form-help-text">{helpText}</div>}
</div>
);
}
}
export default SelectFormField;
回答1:
I've made a redux-form
field using a custom select field named renderSelectField
.
The options items in the select is a regular html
option
:
import { Field, reduxForm } from 'redux-form'
<Field name="type" component={renderSelectField} label="Type">
{materialTypes.map(materialType => {
return (
<option key={materialType} value={materialType}>
{materialType}
</option>
)
})}
</Field>
The renderSelectField
:
import SelectField from 'material-ui/Select'
import FormControl from 'material-ui/Form/FormControl'
import InputLabel from 'material-ui/Input/InputLabel'
import { FormHelperText } from 'material-ui'
const renderSelectField = ({
input,
label,
meta: { touched, error },
children,
...custom
}) => (
<FormControl className="admin-form-field">
<InputLabel error={touched && error}>{label}</InputLabel>
<SelectField
floatingLabelText={label}
error={touched && error}
{...input}
children={children}
{...custom}
/>
<FormHelperText error={touched && error}>{error}</FormHelperText>
</FormControl>
)
No need for redux-form-material-ui
. just redux-form
and material-ui
.
Hope it helps.
来源:https://stackoverflow.com/questions/56181488/redux-form-material-ui-select-with-nested-lists-not-working