React-final-form: Material-UI 3.x example

Created on 26 Oct 2018  路  8Comments  路  Source: final-form/react-final-form

Please do an example that demonstrates how to use Material-UI 3.x input components.

Most helpful comment

Hey, i mounted every material-ui component as a children function:


TextField

// TextField.tsx
import React from 'react';
import MUTextField, { BaseTextFieldProps } from '@material-ui/core/TextField';
import { FieldRenderProps } from 'react-final-form';

const TextField: React.SFC<TextFieldProps & FieldRenderProps> = ({
  input: { name, onChange, value, ...restInput },
  label,
  helperText,
  placeholder,
  meta
}) => (
  <MUTextField
    name={name}
    label={label}
    helperText={meta.touched ? meta.error : helperText}
    error={meta.error && meta.touched}
    placeholder={placeholder}
    onChange={onChange}
    value={value}
    {...restInput}
  />
);

then i mounted it this way:

const {
   name = '',
   label,
   placeholder,
   helperText
} = this.props;
return (
   <Field name={name}>
      {input => (
         <TextField
            {...input}
            label={label}
            placeholder={placeholder}
            type="text"
            helperText={helperText}
            name={name}
         />
      )}
      </Field>
   );


Select

// Select.tsx
import React, { ChangeEventHandler } from 'react';
import { FieldRenderProps } from 'react-final-form';
import TextField, { BaseTextFieldProps } from '@material-ui/core/TextField';
import MenuItem from '@material-ui/core/MenuItem';

import { Suggestion } from '../types';

export interface SelectProps extends BaseTextFieldProps {
  suggestions: Suggestion[];
  label: string;
  onChange?: ChangeEventHandler<HTMLSelectElement>;
  helperText?: string;
  validation: object;
}

const Select: React.SFC<SelectProps & FieldRenderProps> = ({
  input: { name, onChange, value, ...restInput },
  label,
  helperText,
  suggestions
}) => {
  return (
    <TextField
      fullWidth={true}
      select={true}
      label={label}
      value={value}
      onChange={onChange}
      helperText={helperText}
      {...restInput}
    >
      {suggestions.map(suggestion => (
        <MenuItem key={suggestion.value} value={suggestion.value}>
          {suggestion.label}
        </MenuItem>
      ))}
    </TextField>
  );
};

export { Select };

//Render
const {
  name = '',
  label,
  suggestions,
  helperText,
  onChange
} = innerComponentProps as SelectProps;
return (
  <Field name={name}>
    {input => (
      <Select
        {...input}
        suggestions={suggestions}
        label={label}
        helperText={helperText}
        onChange={onChange}
        validation={{}}
        name={name}
      />
    )}
  </Field>
);


Checklist

// Checkbox.tsx
import React, { ChangeEventHandler } from 'react';
import { FieldRenderProps } from 'react-final-form';
import MUCheckbox, {
  CheckboxProps as MUCheckboxProps
} from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';

export interface CheckboxProps extends MUCheckboxProps {
  label: string;
  onChange?: ChangeEventHandler<HTMLInputElement>;
}

const Checkbox: React.SFC<CheckboxProps & FieldRenderProps> = ({
  input: { onChange, checked, value, ...restInput },
  label
}) => {
  return (
    <FormControlLabel
      label={label}
      checked={checked}
      control={<MUCheckbox onChange={onChange} />}
      {...restInput}
    />
  );
};

export { Checkbox };

// Checklist.tsx
import React from 'react';
import { Field } from 'react-final-form';
import FormLabel from '@material-ui/core/FormLabel';
import FormControl from '@material-ui/core/FormControl';
import FormGroup from '@material-ui/core/FormGroup';
import FormHelperText from '@material-ui/core/FormHelperText';

import { CheckboxProps, Checkbox } from './Checkbox';

export interface ChecklistProps {
  label: string;
  checkboxes: CheckboxProps[];
  helperText?: string;
}

const Checklist: React.SFC<ChecklistProps> = ({
  label,
  checkboxes,
  helperText
}) => (
  <FormControl>
    <FormLabel>{label}</FormLabel>
    <FormGroup>
      {checkboxes.map((checkbox, index) => (
        <Field
          key={index}
          name={checkbox.name || ''}
          type="checkbox"
          value={checkbox.value}
        >
          {input => (
            <Checkbox
              {...input}
              label={checkbox.label}
              onChange={checkbox.onChange}
            />
          )}
        </Field>
      ))}
    </FormGroup>
    {helperText && <FormHelperText>{helperText}</FormHelperText>}
  </FormControl>
);

export { Checklist };


RadioGroup

// Radio.tsx
import React from 'react';
import { FieldRenderProps } from 'react-final-form';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import MURadio, { RadioProps as MURadioProps } from '@material-ui/core/Radio';

export interface RadioProps extends MURadioProps {
  label: string;
}

const Radio: React.SFC<RadioProps & FieldRenderProps> = ({
  input: { onChange, value, ...restInput },
  label
}) => (
  <FormControlLabel
    label={label}
    value={value}
    control={<MURadio onChange={onChange} />}
    {...restInput}
  />
);

export { Radio };

// RadioGroup.tsx
import React, { ChangeEventHandler } from 'react';
import { Field } from 'react-final-form';
import FormLabel from '@material-ui/core/FormLabel';
import FormControl from '@material-ui/core/FormControl';
import FormHelperText from '@material-ui/core/FormHelperText';
import { Radio, RadioProps } from './components/Radio';

export interface RadioGroupProps {
  label: string;
  name: string;
  radios: RadioProps[];
  onChange?: ChangeEventHandler<{}>;
  helperText?: string;
}

const RadioGroup: React.SFC<RadioGroupProps> = ({
  radios,
  label,
  name,
  onChange,
  helperText
}) => (
  <FormControl>
    <FormLabel>{label}</FormLabel>
    {radios.map((radio, index) => (
      <Field key={index} name={name} type="radio" value={radio.value}>
        {input => <Radio label={radio.label} onChange={onChange} {...input} />}
      </Field>
    ))}
    {helperText && <FormHelperText>{helperText}</FormHelperText>}
  </FormControl>
);

export { RadioGroup };

// Render
const {
   name,
   label,
   radios,
   helperText,
   onChange
} = this.props;

return (
   <RadioGroup
      name={name}
      label={label}
      radios={radios}
      helperText={helperText}
      onChange={onChange}
   />
);

All 8 comments

+1
Using material-ui 3 does not works!

@cr101 which component is the problem?

@popugang I was just looking for a Material-UI 3 example and since there wasn't one I assumed that it wouldn't work so I haven't tried it yet.

@popugang I was just looking for a Material-UI 3 example and since there wasn't one I assumed that it wouldn't work so I haven't tried it yet.

About v3 and Textfield need to change inputProps to InputProps. Other components working fine

Hey, i mounted every material-ui component as a children function:


TextField

// TextField.tsx
import React from 'react';
import MUTextField, { BaseTextFieldProps } from '@material-ui/core/TextField';
import { FieldRenderProps } from 'react-final-form';

const TextField: React.SFC<TextFieldProps & FieldRenderProps> = ({
  input: { name, onChange, value, ...restInput },
  label,
  helperText,
  placeholder,
  meta
}) => (
  <MUTextField
    name={name}
    label={label}
    helperText={meta.touched ? meta.error : helperText}
    error={meta.error && meta.touched}
    placeholder={placeholder}
    onChange={onChange}
    value={value}
    {...restInput}
  />
);

then i mounted it this way:

const {
   name = '',
   label,
   placeholder,
   helperText
} = this.props;
return (
   <Field name={name}>
      {input => (
         <TextField
            {...input}
            label={label}
            placeholder={placeholder}
            type="text"
            helperText={helperText}
            name={name}
         />
      )}
      </Field>
   );


Select

// Select.tsx
import React, { ChangeEventHandler } from 'react';
import { FieldRenderProps } from 'react-final-form';
import TextField, { BaseTextFieldProps } from '@material-ui/core/TextField';
import MenuItem from '@material-ui/core/MenuItem';

import { Suggestion } from '../types';

export interface SelectProps extends BaseTextFieldProps {
  suggestions: Suggestion[];
  label: string;
  onChange?: ChangeEventHandler<HTMLSelectElement>;
  helperText?: string;
  validation: object;
}

const Select: React.SFC<SelectProps & FieldRenderProps> = ({
  input: { name, onChange, value, ...restInput },
  label,
  helperText,
  suggestions
}) => {
  return (
    <TextField
      fullWidth={true}
      select={true}
      label={label}
      value={value}
      onChange={onChange}
      helperText={helperText}
      {...restInput}
    >
      {suggestions.map(suggestion => (
        <MenuItem key={suggestion.value} value={suggestion.value}>
          {suggestion.label}
        </MenuItem>
      ))}
    </TextField>
  );
};

export { Select };

//Render
const {
  name = '',
  label,
  suggestions,
  helperText,
  onChange
} = innerComponentProps as SelectProps;
return (
  <Field name={name}>
    {input => (
      <Select
        {...input}
        suggestions={suggestions}
        label={label}
        helperText={helperText}
        onChange={onChange}
        validation={{}}
        name={name}
      />
    )}
  </Field>
);


Checklist

// Checkbox.tsx
import React, { ChangeEventHandler } from 'react';
import { FieldRenderProps } from 'react-final-form';
import MUCheckbox, {
  CheckboxProps as MUCheckboxProps
} from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';

export interface CheckboxProps extends MUCheckboxProps {
  label: string;
  onChange?: ChangeEventHandler<HTMLInputElement>;
}

const Checkbox: React.SFC<CheckboxProps & FieldRenderProps> = ({
  input: { onChange, checked, value, ...restInput },
  label
}) => {
  return (
    <FormControlLabel
      label={label}
      checked={checked}
      control={<MUCheckbox onChange={onChange} />}
      {...restInput}
    />
  );
};

export { Checkbox };

// Checklist.tsx
import React from 'react';
import { Field } from 'react-final-form';
import FormLabel from '@material-ui/core/FormLabel';
import FormControl from '@material-ui/core/FormControl';
import FormGroup from '@material-ui/core/FormGroup';
import FormHelperText from '@material-ui/core/FormHelperText';

import { CheckboxProps, Checkbox } from './Checkbox';

export interface ChecklistProps {
  label: string;
  checkboxes: CheckboxProps[];
  helperText?: string;
}

const Checklist: React.SFC<ChecklistProps> = ({
  label,
  checkboxes,
  helperText
}) => (
  <FormControl>
    <FormLabel>{label}</FormLabel>
    <FormGroup>
      {checkboxes.map((checkbox, index) => (
        <Field
          key={index}
          name={checkbox.name || ''}
          type="checkbox"
          value={checkbox.value}
        >
          {input => (
            <Checkbox
              {...input}
              label={checkbox.label}
              onChange={checkbox.onChange}
            />
          )}
        </Field>
      ))}
    </FormGroup>
    {helperText && <FormHelperText>{helperText}</FormHelperText>}
  </FormControl>
);

export { Checklist };


RadioGroup

// Radio.tsx
import React from 'react';
import { FieldRenderProps } from 'react-final-form';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import MURadio, { RadioProps as MURadioProps } from '@material-ui/core/Radio';

export interface RadioProps extends MURadioProps {
  label: string;
}

const Radio: React.SFC<RadioProps & FieldRenderProps> = ({
  input: { onChange, value, ...restInput },
  label
}) => (
  <FormControlLabel
    label={label}
    value={value}
    control={<MURadio onChange={onChange} />}
    {...restInput}
  />
);

export { Radio };

// RadioGroup.tsx
import React, { ChangeEventHandler } from 'react';
import { Field } from 'react-final-form';
import FormLabel from '@material-ui/core/FormLabel';
import FormControl from '@material-ui/core/FormControl';
import FormHelperText from '@material-ui/core/FormHelperText';
import { Radio, RadioProps } from './components/Radio';

export interface RadioGroupProps {
  label: string;
  name: string;
  radios: RadioProps[];
  onChange?: ChangeEventHandler<{}>;
  helperText?: string;
}

const RadioGroup: React.SFC<RadioGroupProps> = ({
  radios,
  label,
  name,
  onChange,
  helperText
}) => (
  <FormControl>
    <FormLabel>{label}</FormLabel>
    {radios.map((radio, index) => (
      <Field key={index} name={name} type="radio" value={radio.value}>
        {input => <Radio label={radio.label} onChange={onChange} {...input} />}
      </Field>
    ))}
    {helperText && <FormHelperText>{helperText}</FormHelperText>}
  </FormControl>
);

export { RadioGroup };

// Render
const {
   name,
   label,
   radios,
   helperText,
   onChange
} = this.props;

return (
   <RadioGroup
      name={name}
      label={label}
      radios={radios}
      helperText={helperText}
      onChange={onChange}
   />
);

@GonzaSanchez: Thanks for your kind help on defining this. Sounds promising, but I could not get this working with my level of understanding when it comes to replicate what you meant by "mounting". I tried importing, but faced with errors and ended up wasting couple of hours just like that. Anyways, thanks!

Open PR for Material-UI 3.0 demo #389

For those of you coming to this issue, I've created a project which wraps all the MUI form components to make using MUI+RFF much easier...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

A11oW picture A11oW  路  3Comments

kavink picture kavink  路  5Comments

Soundvessel picture Soundvessel  路  4Comments

czterystaczwarty picture czterystaczwarty  路  4Comments

antoinerousseau picture antoinerousseau  路  3Comments