title: How to validate my custom input fields before save?
body: <p><strong>&quot;react-admin&quot;: &quot;^3.7.1&quot;</strong></p>
  <pre><code>import {
    Create,
    SimpleForm,
    TextInput,
    SelectInput,
    NumberInput,
    required,
  } from &quot;react-admin&quot;;
  import { getChoices } from &quot;../../utils&quot;;
  
  import RichTextInput from &quot;ra-input-rich-text&quot;;
  import { makeStyles } from &quot;@material-ui/core/styles&quot;;
  import Button from &quot;@material-ui/core/Button&quot;;
  import CloudUploadIcon from &quot;@material-ui/icons/CloudUpload&quot;;
  import EditIcon from &quot;@material-ui/icons/Edit&quot;;
  import CropperModal from &quot;./Modal&quot;;
  import GoodForField from &quot;./goodForField&quot;;
  
  export const MEASUREMENT_UNITS = {
    GM: &quot;GM&quot;,
    PIECE: &quot;Piece&quot;,
    GLASS: &quot;Glass&quot;,
    KATORI: &quot;Katori&quot;,
    CUP: &quot;Cup&quot;,
    BOWL: &quot;Bowl&quot;,
  };
  export const RECIPE_PREPARATION_COMPLEXITY = {
    EASY: &quot;EASY&quot;,
    MEDIUM: &quot;MEDIUM&quot;,
    HARD: &quot;HARD&quot;,
  };
  
  const useStyles = makeStyles((theme) =&gt; ({
    paper: {
      position: &quot;absolute&quot;,
      backgroundColor: theme.palette.background.paper,
      border: &quot;2px solid #000&quot;,
      boxShadow: theme.shadows[5],
      padding: theme.spacing(2, 4, 3),
    },
    root: {
      margin: &quot;10px 0&quot;,
    },
    input: {
      display: &quot;none&quot;,
    },
  }));
  
  const RecipeCreate = (props) =&gt; {
    const classes = useStyles();
    const [open, setOpen] = React.useState(false);
    const [file, setFile] = React.useState(&quot;&quot;);
    const [imageLink, setImageLink] = React.useState(&quot;&quot;);
    const [goodForIds, setGoodForIds] = React.useState([]);
    const imageRef = React.useRef();
    imageRef.current = imageLink;
    const goodForRef = React.useRef();
    goodForRef.current = goodForIds;
    const transform = (data) =&gt; {
      console.log({ imageRef });
      return {
        ...data,
        image_url: imageRef.current,
        good_for: goodForRef.current,
      };
    };
  
    const handleOpen = () =&gt; {
      setOpen(true);
    };
  
    const handleClose = () =&gt; {
      setOpen(false);
    };
  
    const handleChangeFileInput = (e) =&gt; {
      setFile(e.target.files[0]);
      handleOpen();
    };
    const handleClickEdit = () =&gt; {
      setFile(imageLink);
      handleOpen();
    };
  
    return (
      &lt;&gt;
        &lt;CropperModal
          open={open}
          handleClose={handleClose}
          file={file}
          handleImageLink={setImageLink}
          handleVisibility={setOpen}
        /&gt;
        &lt;Create transform={transform} {...props}&gt;
          &lt;SimpleForm redirect={false}&gt;
            {imageLink &amp;&amp; (
              &lt;div
                style={{
                  display: &quot;flex&quot;,
                  width: &quot;100px&quot;,
                  height: &quot;100px&quot;,
                  marginBottom: &quot;20px&quot;,
                  position: &quot;relative&quot;,
                }}
              &gt;
                &lt;img
                  src={imageLink}
                  alt=&quot;dish&quot;
                  style={{
                    width: &quot;100px&quot;,
                    height: &quot;100px&quot;,
                    border: &quot;5px solid #c9c5c5&quot;,
                    cursor: &quot;pointer&quot;,
                  }}
                  onClick={handleClickEdit}
                /&gt;
                &lt;EditIcon
                  onClick={handleClickEdit}
                  style={{
                    position: &quot;absolute&quot;,
                    cursor: &quot;pointer&quot;,
                    right: &quot;-10px&quot;,
                    bottom: &quot;-10px&quot;,
                    backgroundColor: &quot;#c9c5c5&quot;,
                    fontSize: &quot;1.2rem&quot;,
                  }}
                /&gt;
              &lt;/div&gt;
            )}
            &lt;div className={classes.root}&gt;
              &lt;input
                accept=&quot;.png, .jpg, .jpeg&quot;
                className={classes.input}
                id=&quot;contained-button-file&quot;
                multiple
                type=&quot;file&quot;
                onChange={handleChangeFileInput}
              /&gt;
              &lt;label htmlFor=&quot;contained-button-file&quot;&gt;
                &lt;Button
                  style={{ textTransform: &quot;none&quot; }}
                  startIcon={&lt;CloudUploadIcon /&gt;}
                  variant=&quot;contained&quot;
                  color=&quot;primary&quot;
                  component=&quot;span&quot;
                &gt;
                  {imageLink ? &quot;Upload new&quot; : &quot;Upload picture&quot;}
                &lt;/Button&gt;
              &lt;/label&gt;
            &lt;/div&gt;
            &lt;TextInput source=&quot;name&quot; validate={required()} /&gt;
            &lt;SelectInput
              source=&quot;measurement_unit&quot;
              lable=&quot;Measurement Unit&quot;
              choices={getChoices(MEASUREMENT_UNITS)}
              validate={required()}
            /&gt;
            &lt;TextInput validate={required()} source=&quot;description&quot; multiline /&gt;
            &lt;RichTextInput source=&quot;recipe&quot; validate={required()} /&gt;
            &lt;TextInput
              validate={required()}
              source=&quot;preparation_time&quot;
              lable=&quot;Preparation time&quot;
            /&gt;
  
            &lt;SelectInput
              validate={required()}
              source=&quot;preparation_complexity&quot;
              label=&quot;Preparation Complexity&quot;
              choices={getChoices(RECIPE_PREPARATION_COMPLEXITY)}
            /&gt;
            &lt;GoodForField goodForIds={goodForIds} setGoodForIds={setGoodForIds} /&gt;
            &lt;NumberInput validate={required()} source=&quot;calories&quot; /&gt;
            &lt;NumberInput validate={required()} source=&quot;carbs&quot; /&gt;
            &lt;NumberInput validate={required()} source=&quot;protein&quot; /&gt;
            &lt;NumberInput validate={required()} source=&quot;fats&quot; /&gt;
            &lt;NumberInput validate={required()} source=&quot;fibre&quot; /&gt;
            &lt;TextInput source=&quot;preparation_video_link&quot; label=&quot;Video url&quot; /&gt;
          &lt;/SimpleForm&gt;
        &lt;/Create&gt;
      &lt;/&gt;
    );
  };
  </code></pre>
  <p>I am using Create component of react-admin to create the recipe resource. I also have an image scource through which I am uploading the image to cloud storage and later passing the url to create throught transform function.
  <strong>CropperModal</strong>  is a component that is used to crop the image and upload the image to cloud stoarge. When the form is submitted I am passing the image URL to the request body with the help of transform function. My problem is how can I validate this custom field before save ?</p>
  <p>Note: <strong>CropperModal</strong> is purely a custom component, not using any of the react-admin utilities.</p>