8

In a react-admin project I created my own toolbar button that should display a confirmation dialog, similar to the JavaScript alert but not quite as ugly.

Only when the user clicks OK, things should happen, in my case some database operations.

is there an ootb alert dialog in react-admin or what is an easy way to create one? I could not find anything in the docs about that topic. I tried the alert example from material ui (see https://v1.material-ui.com/demos/dialogs/) but due to my very limited understandig of react I am not able to create a reusable component from the example.

Update:
The code snippet below illustrates what I'd like to do:

// Definition of a toolbar button
const ActionButton = ({ handleSubmitWithRedirect, ...props }) => {
    const form = useForm();
    var formdata = form.getState().values;

    switch (formdata.status.id) {
        case 0:
            props.label = "Text for state 0";
            break;
        case 1:
            props.label = "Text for state 2";
            break;
        default:
            props.label = "Unknown state"
    }

    const handleClick = useCallback(() => {
        switch (formdata.status.id) {
            case 0:
                form.change('status', status[1]);
                break;
            case 1:
                // Here I want to open a confirmation Dialog...
                if( openAlertDialog("Warning, things will happen","Okay","Better not")) 
                {
                    form.change('status', status[2]);
                    createDatabaseRecord(formdata).then(() => (
                        // success handling [...]
                    ),
                    () => (
                        // error handling [...]
                    ))
                };
                break;
            default:
        }
        handleSubmitWithRedirect('list');
    }, [formdata, form]);
    return <SaveButton {...props} handleSubmitWithRedirect={handleClick} />;
};
elsni
  • 1,953
  • 2
  • 17
  • 35

4 Answers4

4

There is actually a Confirm component which can be used in a toolbar button like this:

const ExampleButton = ({ handleSubmitWithRedirect, handleSubmit, ...props }) => {
    const form = useForm();
    const notify = useNotify();
    const [open, setOpen] = React.useState(false);
    const handleClick = () => setOpen(true);
    const handleDialogClose = () => setOpen(false);

    const handleConfirm = () => {
        doStuff();
        notify('Stuff is done.');
        handleSubmit();
        setOpen(false);
    };

    var ct = "Do you really want to do stuff?";
    return (<><SaveButton {...props} handleSubmitWithRedirect={handleClick} handleSubmit={handleClick} variant="outlined" />
        <Confirm
            isOpen={open}
            title="do stuff"
            content={ct}
            onConfirm={handleConfirm}
            onClose={handleDialogClose}
            confirm="Yep"
            cancel="Nope"
        />
    </>);
}
elsni
  • 1,953
  • 2
  • 17
  • 35
1

Check out the following codesandbox for an example on how to trigger opening a dialog using Material-UI as well as triggering different actions based on whether you click the "Agree" or "Disagree" buttons.

https://codesandbox.io/s/material-demo-cspqy

  • thanks, looks great! I added a code snippet to illustrate what I'd like to do. Unfortunately I am not able to rewrite your example to fit my needs – elsni Feb 21 '20 at 08:31
  • 1
    Still have no solution, I use javascript ````window.confirm()```` but it is ugly... – elsni Mar 03 '20 at 08:58
0

In case it interests anyone, this is the OK/Cancel Dialog I made. It was too hard to close the dialog within the component. I had to have that logic outside the component, but I couldnt find any other way of achieving the closing logic.

//Test.tsx
function Test() {
    const [open, setOpen] = React.useState(false);
    const handleOpen = () => setOpen(true);
    const handleClose = () => setOpen(false);
    return (
        <>
            <Button onClick={handleOpen}> Delete Category</Button>
            {open && <OKCancelDialog open={true} title={"Delete Thing!"}
                                     content={"Are you sure you want to delete thing?"}
                                     handleOK={() => {
                                         handleClose();
                                         alert("yeah")
                                     }}
                                     handleCancel={() => {
                                         handleClose();
                                         alert("cancel")
                                     }}/>}
        </>
    )
}

//OKCancelComponent.tsx
type Props = {
    title: string,
    content: string,
    handleOK: () => any,
    open: boolean
    handleCancel: () => any
}

export default function OKCancelDialog(props: Props) {
    return (
        <Dialog
            open={props.open}
            onClose={props.handleCancel}
            aria-labelledby="alert-dialog-title"
            aria-describedby="alert-dialog-description"
        >
            <DialogTitle id="alert-dialog-title">
                {props.title}
            </DialogTitle>
            <DialogContent>
                <DialogContentText id="alert-dialog-description">
                    {props.content}
                </DialogContentText>
            </DialogContent>
            <DialogActions>
                <Button onClick={props.handleOK}>
                    OK
                </Button>
                <Button startIcon={<CancelIcon/>} onClick={props.handleCancel}>Cancel</Button>
            </DialogActions>
        </Dialog>
    );
}
Oliver Watkins
  • 12,575
  • 33
  • 119
  • 225
0

In my case I made a new component "ButtonConfirm".

import React from 'react';

class ButtonConfirm extends React.Component
 {
    constructor(props)
    {
        super(props)

        this.state = {
            title: this.props.title,
            classButtonName: 'buttonForm buttonAlert',
            classDialogName: 'dialog_alert',
            query: this.props.query,
            param: "del",
            param_id: "-1",
            view: "button"
        }
        
    }

    showDialog()
    {
        this.setState({
            view: "query"
        });
        
    }

    onClickYes()
    {
        this.setState({
            view: "button"
        }); 

        this.props.onConfirm("yes",this.state.param, this.state.param_id);
    }

    onClickNo()
    {
        this.setState({
            view: "button"
        });

        this.props.onConfirm("no",this.state.param, this.state.param_id);
    }

    render()
    {
        if(this.state.view == "button")
        {
            return (
                <div className={this.state.classButtonName} onClick={this.showDialog.bind(this) }>{this.state.title}</div>
            );
        }

        if(this.state.view == "query")
        {
            return (
                <div className={this.state.classDialogName}>
                    <div>{this.state.title}</div>
                    <div className='container'>
                        <div>{this.state.query}</div>
                        <div className={this.state.classButtonName} onClick={this.onClickYes.bind(this) } >YES</div>
                        <div className={this.state.classButtonName} onClick={this.onClickNo.bind(this) } >NO</div>
                    </div>
                </div>
            );
        }
    }
 }

 export default ButtonConfirm;    

Then in my "top" component I created new method

 onConfirmDel(type, param, id)
        {
           console.log(type + param + id);
        }

And in render method:

<ButtonConfirm  onConfirm={this.onConfirmDel.bind(this) }  title="Delete" query="Are you sure...?"  />

If you want to use that, you will need css style :)

Blazej Kita
  • 99
  • 1
  • 1
  • 10