Redux Form Material UI:选择嵌套列表不起作用

Posted

技术标签:

【中文标题】Redux Form Material UI:选择嵌套列表不起作用【英文标题】:Redux Form Material UI: Select with Nested Lists not working 【发布时间】:2019-10-04 11:53:17 【问题描述】:

我有一种情况需要显示项目的分组列表:https://v0.material-ui.com/#/components/list(转到嵌套列表)

    redux-form Select 字段能否使用 <ListItem /> 而不是 <MenuItem /> 的选项?

    我无法从嵌套下拉列表中选择任何项目。 Redux 的 onChange 回调没有启动。

代码如下: 表格:

<form>
    <Field
            name="camops"
            normalize=normalizeMultipleSelectValues
            component=MySelectFormField
            floatingLabelText="Item(s)"
            fullWidth
            multiple
          />
</form>

组件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;

组件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">*&nbsp;</span>

        !!helpText && <div className="form-help-text">helpText</div>
      </div>
    );
  


export default SelectFormField;

【问题讨论】:

【参考方案1】:

我使用名为 renderSelectField 的自定义选择字段创建了一个 redux-form 字段。

select中的options项是普通的htmloption

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>

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>
)

不需要redux-form-material-ui。只是redux-formmaterial-ui

希望对您有所帮助。

【讨论】:

以上是关于Redux Form Material UI:选择嵌套列表不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Material-UI 和 Redux-form,点击 select 时重新渲染选项,如何防止?

使用material-ui为redux-form设置initialValues无效

使用 Redux/React 的 Material UI TablePagination 句柄

反应 |还原形式 |材料-ui |如何将 DatePicker 与我的表单结合使用

带有 Redux 的 Material UI v1 - 如何导出

使用带有 reactjs 和 redux 的 Material-ui 复选框