vijayscode
vijayscode

Reputation: 2015

Close Persistent Material UI Drawer on clicking outside

I am trying to use Drawer component in Material UI React. I want that state inside the Drawer component should not lost on closing of Drawer component, hence I'm passing variant="persistent" in Drawer component.

Now, the problem is that the Persistent Drawer does not provide backdrop functionality by default unlike temporary drawers hence I'm unable to close it on outside click. I tried {{ModalProps={{ onBackdropClick: this.toggleDrawer }} }} also but still it is not working.

Is there any workaround for this?

Material UI Version: 1.0.0

CodeSandbox link

Upvotes: 30

Views: 51352

Answers (10)

coot3
coot3

Reputation: 632

If you want to use the "temporary" variant and retain state when opening and closing the drawer, you can pass the keepMounted: true prop to ModalProps of the drawer.

<Drawer 
  variant="temporary"
  ModalProps={{
    keepMounted: true,
  }}
>
 {children}
</Drawer>

Upvotes: 2

Arian Nargesi
Arian Nargesi

Reputation: 551

For searchers how have problem with closing the drawer when clicking outside, you can simply detect outside click in onClose prop. it takes a function and runs it when you click outside of the drawer.

<Drawer open={state} onClose={() => setState(false)} >
</Drawer>

Upvotes: 1

Jairo arcy
Jairo arcy

Reputation: 1

You can use in Drawer's open attribute a useState and set to false in the onClose property:

onClose={() => setOpen(false)}

in this example, the useState name is ** open ** and ** setOpen **

Upvotes: 0

NearHuscarl
NearHuscarl

Reputation: 81270

Working solution in MUI v5:

Persistent Drawer

Use ClickAwayListener to know when the user clicks outside the Drawer. You also need to set mouseEvent="onMouseDown", otherwise the onClickAway callback is fired after the user clicks the open button and make the Drawer close immediately before it can be opened.

<ClickAwayListener
  mouseEvent="onMouseDown"
  touchEvent="onTouchStart"
  open={open}
  onClickAway={() => open && setOpen(false)}
>
  <Drawer variant="persistent" {...props} />
</ClickAwayListener>

Temporary Drawer

<Drawer
  variant="temporary"
  open={open}
  onClose={(_, reason) =>
    reason === 'backdropClick' && setOpen(false)
  }
>

Live Demo

Codesandbox Demo

Upvotes: 12

Rasmus Puls
Rasmus Puls

Reputation: 3219

For the sake of searchers landing on this question. If you are having trouble with ClickAwayListener and are not using variant='persistent'. Try this instead: Providing a toggle function to ModalProps onBackdropClick

<Drawer
  open={drawerIsOpen}
  ModalProps={{ onBackdropClick: this.toggleDrawer }}
>
  <MenuItem>drawer item 1</MenuItem>
</Drawer>

UPDATE July 2021:

I recently updated material-ui/core to version 4.12.1 and noticed that onBackdropClick is being deprecated. Instead they have added native support for this functionality, the onClose function will be called automatically when clicking outside the drawer, and it now gives a reason for why it was called:

Signature: function(event: object, reason: string) => void

event: The event source of the callback.

reason: Can be: "escapeKeyDown", "backdropClick"

See example here: https://material-ui.com/api/modal/ scroll down to onBackDropClicked - it works the same for the drawer as it does for the

Do this instead:

<Drawer
  open={drawerIsOpen}
  onClose={{ (ev, reason) => this.setState({ drawerIsOpen: false }) }}
>
  <MenuItem>drawer item 1</MenuItem>
</Drawer>

Upvotes: 40

saiteja konda
saiteja konda

Reputation: 31

Recently found out about this neat useOnClickOutside hook => CodeSandBox and replaced all my with it. Much more elegant than adding an element to the dom and really easy to use with Mui now that you can pass a ref prop to any Material-ui component.

Upvotes: 0

Mikalov
Mikalov

Reputation: 11

I am not sure if it works with 1.0.0 version but this approach works for me noting that i am using the drawer from "material-ui/core @4.10"

<Drawer ... open={this.state.open} onClose={() => this.handleDrawerClose()}>
....
</Drawer>

Upvotes: 0

Dennis Callejas
Dennis Callejas

Reputation: 181

I spend some time training to fix this, but I found a really a useful solution and is to change the variant to Temporary and use de onEscapeKeyDown and the onBackdropClick as follow:

  <Drawer
    variant="temporary"
    onEscapeKeyDown={handleDrawerClose}
    onBackdropClick={handleDrawerClose}
    open={open}
    ...rest of your code...

Upvotes: 18

Josh Wooding
Josh Wooding

Reputation: 852

You can use the ClickAwayListener component for this.
https://material-ui.com/api/click-away-listener/

import ClickAwayListener from '@material-ui/core/ClickAwayListener';

const drawer = (
      <ClickAwayListener onClickAway={this.handleDrawerClose}>
        <Drawer
          variant="persistent"
          anchor={anchor}
          open={open}
          classes={{
            paper: classes.drawerPaper
          }}
        >
          <div className={classes.drawerHeader}>
            <IconButton onClick={this.handleDrawerClose}>
              {theme.direction === "rtl" ? (
                <ChevronRightIcon />
              ) : (
                <ChevronLeftIcon />
              )}
            </IconButton>
          </div>
          <Divider />
          <List>a asdasd</List>
          <Divider />
          <List>asdasd</List>
        </Drawer>
      </ClickAwayListener>
    );

https://codesandbox.io/s/072ny1rjw

Upvotes: 21

milo
milo

Reputation: 976

You can implement this yourself by adding a div in your appFrame which has an onClick that closes the drawer like this:

<div className={classes.appFrame}>
{this.state.open ? 
    <div style={{ position: "fixed", zIndex: 1, left: 0, right: 0, top: 0, bottom: 0 }} 
        onClick={() => this.handleDrawerClose()} /> 
    : null
}
// rest of your code

Upvotes: 4

Related Questions