Ad

Can't Add Items To Material-ui Form

- 1 answer

I got handed down a project from someone else and I need to add some items to a form created with react and material-ui. I can get text fields to work but if I try to add a dropdown, it doesn't hold the value when selected.

I followed the same conventions of adding the items to the form that the guy who created this form used.

I added a grid item with a formcontrol component inside of it. There was also defaultprops set with a "game" object inside, that had all of the form fields as properties. I added the new field items to there also.

Here is the whole form component because I'm not really sure where the problem actually is.

import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import history from '~/utils/history';
import { FormControl, Button, TextField, Grid, MenuItem, FormHelperText } from '@material-ui/core';
import { DateTimePicker } from 'material-ui-pickers';
import gameState from '~/utils/enums';
import { dateTime } from '~/utils/formats';

import { getById, create, update, remove } from '~/services/games';
import { getAll as getLeagues } from '~/services/leagues';
import { getAll as getSeasons } from '~/services/seasons';
import { getAll as getTeams } from '~/services/teams';

const GameForm = ({ game, id }) => {
  useEffect(() => {
    console.log({ form, game });
  });

  const [edit, setEdit] = useState(false);
  const [form, setForm] = useState(game);
  const [error, setError] = useState('');
  const [variant, setVariant] = useState('outlined');

  const [leagues, setLeagues] = useState([]);
  const [seasons, setSeasons] = useState([]);
  const [teams, setTeams] = useState([]);
  const [gametype, setGametype] = useState(1);

  const gametypes = [
    { key: 0, value: 'Series Game' },
    { key: 1, value: 'Playoff' },
    { key: 2, value: 'Final' },
    { key: 3, value: 'Else' }
  ];

  useEffect(() => {
    getSeasons()
      .then(({ data }) => {
        setSeasons(data);
        return getLeagues();
      })
      .then(({ data }) => {
        setLeagues(data);
        if (id) {
          getById(id).then(({ data }) => setForm(data));
        } else {
          setEdit(true);
        }
      });
  }, []);

  useEffect(() => {
    if (edit) {
      setVariant('outlined');
    } else {
      setVariant('standard');
    }
  }, [edit]);

  useEffect(() => {
    if (form.league) {
      getTeams({ leagues: [form.league] }).then(({ data }) => setTeams(data));
    }
  }, [form.league]);

  useEffect(() => {
    if (form.gametype) {
      setGametype('Playoff');
    }
  }, [form.gametype]);

  const handleChange = ({ target }) => {
    let { name, value } = target;
    setForm({
      ...form,
      [name]: value
    });
  };

  const handleDateChange = formInputName => {
    const dateHandler = moment => {
      setForm({
        ...form,
        [formInputName]: moment ? moment.toDate() : null
      });
    };
    return dateHandler;
  };

  const handleFormSubmit = () => {
    if (!edit) {
      setEdit(true);
    } else {
      new Promise(resolve => {
        resolve(form._id ? update(form) : create(form));
      })
        .then(() => {
          history.push('/games');
        })
        .catch(error => setError(error.response.data.error));
    }
  };
  const handleDelete = () => {
    if (window.confirm(`Delete permanently?`)) {
      remove(id).then(() => history.goBack());
    }
  };

  const handleCancel = () => {
    if (edit && id) {
      setEdit(false);
    } else {
      history.goBack();
    }
  };
  return (
    <Grid container spacing={8} justify="space-between">
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            required
            select
            id="season"
            name="season"
            label="Season"
            variant={variant}
            disabled={!edit}
            value={form.season}
            onChange={handleChange}
          >
            {seasons.map(option => (
              <MenuItem key={option.name} value={option._id}>
                {option.name}
              </MenuItem>
            ))}
          </TextField>
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            required
            select
            id="league"
            name="league"
            label="League"
            variant={variant}
            disabled={!edit}
            value={form.league}
            onChange={handleChange}
          >
            {leagues.map(option => (
              <MenuItem key={option.name} value={option._id}>
                {option.name}
              </MenuItem>
            ))}
          </TextField>
        </FormControl>
      </Grid>
      <Grid item xs={12}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <DateTimePicker
            required
            id="start"
            name="start"
            label="Game starts"
            variant={variant}
            disabled={!edit || !form.season}
            autoOk
            ampm={false}
            keyboard
            clearable
            minDate={form.season ? seasons.find(({ _id }) => _id === form.season).start : undefined}
            minDateMessage="Cannot start before the season begins"
            maxDate={form.season ? seasons.find(({ _id }) => _id === form.season).end : undefined}
            maxDateMessage="Cannot start after the end of the season"
            value={form.start}
            onChange={handleDateChange('start')}
            {...dateTime}
          />
          <FormHelperText disabled={!form.season}>
            {!form.season ? 'Select season first' : undefined}
          </FormHelperText>
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            required
            select
            id="home"
            name="home"
            label="Home team"
            variant={variant}
            disabled={!edit || !form.league}
            helperText={!form.league ? 'Select league first' : undefined}
            value={form.home}
            onChange={handleChange}
          >
            <MenuItem value="">
              <em>None</em>
            </MenuItem>
            {teams
              .filter(({ _id }) => _id !== form.away)
              .map(option => (
                <MenuItem key={option.name} value={option._id}>
                  {option.name}
                </MenuItem>
              ))}
          </TextField>
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            required
            select
            id="away"
            name="away"
            label="Team away"
            variant={variant}
            disabled={!edit || !form.league}
            helperText={!form.league ? 'Select league first' : undefined}
            value={form.away}
            onChange={handleChange}
          >
            <MenuItem value="">
              <em>None</em>
            </MenuItem>
            {teams
              .filter(({ _id }) => _id !== form.home)
              .map(option => (
                <MenuItem key={option.name} value={option._id}>
                  {option.name}
                </MenuItem>
              ))}
          </TextField>
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            required
            select
            id="gametype"
            label=" Game type"
            variant={variant}
            disabled={!edit}
            value={form.gametype}
            onChange={handleChange}
          >
            <MenuItem value="">
              <em>None</em>
            </MenuItem>
            {gametypes.map(option => (
              <MenuItem key={option.key} value={option.value}>
                {option.value}
              </MenuItem>
            ))}
          </TextField>
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            text
            id="umpire"
            label="Umpire"
            variant={variant}
            disabled={!edit || !form.league}
          />
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            text
            id="scorekeeper"
            label="Scorekeeper"
            variant={variant}
            disabled={!edit || !form.league}
          />
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            text
            id="referee1"
            label="Referee 1"
            variant={variant}
            disabled={!edit || !form.league}
          />
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            text
            id="referee2"
            label="Referee 2"
            variant={variant}
            disabled={!edit || !form.league}
          />
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            text
            id="referee3"
            label="Referee 3"
            variant={variant}
            disabled={!edit || !form.league}
          />
        </FormControl>
      </Grid>
      <Grid item xs={edit && id ? 4 : 6}>
        <Button variant="outlined" color="secondary" fullWidth onClick={handleCancel}>
          {edit && id ? 'Cancel' : 'Back'}
        </Button>
      </Grid>
      {edit && id ? (
        <Grid item xs={4}>
          <Button
            type="submit"
            variant="contained"
            color="secondary"
            fullWidth
            onClick={handleDelete}
          >
            Delete
          </Button>
        </Grid>
      ) : null}
      <Grid item xs={edit && id ? 4 : 6}>
        <Button
          type="submit"
          variant="outlined"
          color="primary"
          fullWidth
          onClick={handleFormSubmit}
        >
          {edit ? (id ? 'Save' : 'Create') : 'Edit Game'}
        </Button>
      </Grid>
      {!edit ? (
        <Grid item xs={12}>
          <Button
            variant="outlined"
            color="primary"
            fullWidth
            onClick={() => {
              history.push('/games/' + id + '/scores');
            }}
          >
            EDIT SCORES
          </Button>
        </Grid>
      ) : null}
    </Grid>
  );
};

GameForm.defaultProps = {
  game: {
    season: '',
    league: '',
    start: null,
    home: '',
    away: '',
    gametype: '',
    umpire: '',
    scorekeeper: '',
    referee1: '',
    referee2: '',
    referee3: ''
  }
};

GameForm.propTypes = {
  //classes: PropTypes.object.isRequired,
  game: PropTypes.object
};

export default GameForm;

I noticed that if I print the game object to the console, it only shows the old form items and not the new ones I added. The new items are: gametype, umpire, scorekeeper, referee1-3.

I've been trying to make this work for a few days already, so any help would really be appreciated.

Ad

Answer

you need onChange={handleChange} in those and you also need to provide the name as props

BTW, I highly recommend you to combine those useStates as one single state object

For example, an alternative banned multiple useState() calls in a component. You’d keep state in one object.

function Form() {
  const [state, setState] = useState({
    edit: '',
    form: '',
    error: '',
  });
  // ...
}

To be clear, Hooks do allow this style. You don’t have to split your state into a bunch of state variables (see doc).

Ad
source: stackoverflow.com
Ad