4

In a complex tabbed form in react-admin I need to have two submit buttons, one is the regular save button and one for altering the "status" field (advancing one workflow step) and saving the form.

The save butten should only become active if all required fields are filled by the user. The other button changes its text depending on a "status" field in the record which contains the current workflow step, and is only active when the form validation for the current workflow step passes.

So either I need a dynamic button or several buttons which show and hide depending on the "status" field. I think the dynamic button would be the more elegant solution.

Below you see the code I currently have, it is more or less copied from the react-admin documentation. I need to add a custom save button as well, but it is just a subset, easy to do when the AdvanceWorkflowButton works at the end.

const AdvanceWorkflowButton= ({ handleSubmitWithRedirect, ...props }) => {
    const [create] = useCreate('posts');
    const redirectTo = useRedirect();
    const notify = useNotify();
    const { basePath, redirect } = props;
    const form = useForm();

    // I need to set the label dynamically ... how?
    // I also need sth like:
    // if (validationSucceeds()) enable=true

    const handleClick = useCallback(() => {
        // here I need to check the current content of the "status" field.... how?
        form.change('status', { "id": 2, "name": "Vorbereitung begonnen" });
        handleSubmitWithRedirect('list');
    }, [form]);

    return <SaveButton {...props} handleSubmitWithRedirect={handleClick} />;
};

const CustomToolbar = props => (
    <Toolbar {...props} >
        <SaveButton
            label="Speichern"
            redirect="list"
            submitOnEnter={true}
            variant="text"
        />
       <AdvanceWorkflowButton />
    </Toolbar>
);
elsni
  • 1,953
  • 2
  • 17
  • 35

1 Answers1

2

I had the exact same trouble.

Needed a button to save the form without validation, and another to save and change status with validation in place.

The code above helped me get to the answer, here are my configuration of the components necessary to achieve the desired outcome.

Set a new truthy value up in the form data as follows when the user clicks the save and next. Check the new property ('goNextStep' in our example) on the server to move the process forward.

<SaveButton
    label="Save and next step"
    handleSubmitWithRedirect={() => {
        form.change('goNextStep', 1); // or true
        props.handleSubmitWithRedirect('list');
    }}
</SaveButton>
<SaveButton
    label="Save only"
    handleSubmitWithRedirect={() => {
        form.change('validateCustom', 0); // or false
        props.handleSubmitWithRedirect('list');
    }}
/>

Use the validate prop on react-admin form. I could not make it work with field level validations. I had to remove every field level validation props, and implement all those in validateFunction. Altough, you could still use the validators in your custom validation function.

const validateFunction = (values) =>{
    // using our previously set custom value, which tells us which button the user clicked
    let shouldValidate = values.goNextStep === 1;
    
    // return undefined if you dont want any validation error
    if (!shouldValidate) return undefined;
    
    let errors = {};
    
    // use built in validations something like this
    var someTextFieldErrorText = required()(values.someTextField, values);
    if (someTextFieldErrorText) {
        errors.someTextFieldErrorText = someTextFieldErrorText;
    }

    // OR write plain simple validation yourself
    if(!values.someTextField) {
        errors.someTextField = 'Invalid property!';
    }
    
    return Object.keys(errors) ? errors : undefined;
}

Than set up tabbed form to use the previous function for validation.

<TabbedForm
    validate={validateFunction}
>
...
</TabbedForm

React-admin version: 3.10.1

Gergo
  • 131
  • 1
  • 6