Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select with Nested Lists not working #289

Open
saranshbansal opened this issue May 17, 2019 · 0 comments
Open

Select with Nested Lists not working #289

saranshbansal opened this issue May 17, 2019 · 0 comments

Comments

@saranshbansal
Copy link

I have a situation where I need to show grouped lists of items: https://v0.material-ui.com/#/components/list (Go to Nested Lists)

  1. Can redux-form Select field work with options as <ListItem /> instead of <MenuItem /> ?

  2. 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">*&nbsp;</span>}

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

export default SelectFormField;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant