React-modal: draggable feature

Created on 26 Sep 2016  路  18Comments  路  Source: reactjs/react-modal

will you support draggable feature in the near future, trying to use react-draggable with this component but dont get any joy, thanks

bug

Most helpful comment

Here's a working example of how you can do this, using react-modal and react-draggable.

The gist of what's going on is, you create your own "content" div and basically ignore/hide the one provided by react-modal.

All 18 comments

@parlop did you found a way to solve this issue with react-draggable? this is seems a nice combination.

yes, I solved this issue with the library react-draggable(https://github.com/mzabriskie/react-draggable), it works like a charm, thanks!

Awesome! Thanks!

@parlop can you show your solution? I have the same problem.

@parlop Any details you can share to help the community? How did you make it work? We are having trouble with the Portal -> #45

@diasbruno Maybe you have some insights? Otherwise, maybe we should reopen the issue?

@eldamir I was thinking about it and I don't think this is what a modal should do. I would recommend some kind of 'window', not a modal.

actually I made it work with a hack, you have to put draggable before a div content:

<Modal><Draggable><div className="whatever">content</div></Draggable></Modal>

It works for me and give it a high z-index
here's the code i used


 return (
      <div>
        <button style={buttonstyle} onClick={this.openModal}><i className="fa fa-search"></i>Search Json</button>
        <Modal
          contentLabel="????"
          className="Modal__Bootstrap modal-dialog"
          closeTimeoutMS={150}
          isOpen={this.state.modalIsOpen}
          onRequestClose={this.handleModalCloseRequest}
          shouldCloseOnOverlayClick={false}
          style={customStyles}
        > <Draggable>
          <div className="modal-content">
            <div className="modal-header">
              <button type="button" className="close" onClick={this.handleModalCloseRequest}>
                <span aria-hidden="true">&times;</span>
                <span className="sr-only">Close</span>
              </button>
              <h4 className="modal-title">Search Json </h4>
            </div>
            <div className="modal-body">
              <SearchModalComp closeMenu={this.closeMenu} {...this.props}/>
            </div>            
            <div className="modal-footer">
              <button type="button" className="btn btn-primary" onClick={this.handleSaveClicked}>Select</button>
              <button type="button" className="btn btn-default" onClick={this.handleModalCloseRequest}>Close</button>
            </div>
          </div></Draggable>
        </Modal>

      </div>
    );

Thanks @parlop , I'll give it a try

Having trouble getting this working with react-draggable. It just drags the form inside:
http://i.imgur.com/iCRjZL5.png

Code:

        <Col sm={3}>
          <Modal>
            <Draggable>
              <div>
                <Modal.Body>
                  <ModalContentStuff {...this.props} closeAction={this.close.bind(this)} />
                </Modal.Body>
              </div>
            </Draggable>
          </Modal>
        </Col>

ModalContentStuff contains <Form><FormGroup>...

Any ideas?

@parlop @austingayler for me, this just resulted in the modal becoming an empty div, for some reason. The Draggable seems to ignore its children for some reason...

For your reference, I ended up abandoning react-draggable and just using good ol' JQuery

export class Dialog extends React.Component<DialogProps, any> {
    render() {
        [...]
        return (
            <Modal isOpen={props.isOpen}
                   contentLabel={props.contentLabel}
                   shouldCloseOnOverlayClick={props.shouldCloseOnOverlayClick}
                   className={modalCSS}
                   overlayClassName={overlayCSS}
                   onAfterOpen={props.onAfterOpen}>
                <div ref={(div) => {
                    const target = $(div).parent();
                    target.draggable({handle: `.${dragHandle}`});
                    this.props.forcedWidth && target.width(this.props.forcedWidth);
                }}>
                    <ModalHeader title={props.contentLabel}
                                 onTickerClick={props.onClose}
                                 className={dragHandle} />
                    <ModalBody>
                        {props.children}
                    </ModalBody>
                </div>
            </Modal>
        );
    }
}

The key takeaway here is using ref to grab the DOM element and applying draggable. There was an issue with the width becoming 100% for some reason, but I've just managed it with props and a subsequent call to JQuery.width()

What do you set dragHandle to? I guess I don't understand the parent context here, and I get a runtime error because that variable is undefined. EDIT: I set it to "modal-header", but then the ref function throws an error saying that target has no function draggable. The div parent is a Modal object, just as in your example, so I don't know what's going wrong.

My dragHandle varialbe is just the classname of the <ModalHeader />, so that I can drag the dialog by clicking down on the header bar

Here's a working example of how you can do this, using react-modal and react-draggable.

The gist of what's going on is, you create your own "content" div and basically ignore/hide the one provided by react-modal.

@davvidbaker Is there a way to use yours while allowing one to interact with the background UI? I'm using a style override like:

        style={{
          overlay: {
            position: 'fixed',
            zIndex: '99',
            height: '400px',
            width: '400px',
            padding: 'initial',
            margin: 'auto',
            top: '0',
            left: '0',
            right: '0',
            bottom: '0',
            border: 'none',
            background: 'transparent',
            borderRadius: '0'
          },
          content: {
            position: 'static',
            height: '100%',
            width: '100%',
            padding: '10px',
            top: 'auto',
            left: 'auto',
            right: 'auto',
            bottom: 'auto',
            background: '#fff',
            outline: 'none',
            overflow: 'auto'
          }
        }}

In order to start the modal and its overlay in the middle without covering up the background UI.

One thing I'm concerned about is the ReactModal__Content div. That is set to transparent, however it still exists in the DOM, that means it can cover up the background UI, which is exactly what I want to avoid.

Is there no way to attach Draggable directly to the ReactModal__Overlay div?

I think what you want to do will work if you add pointerEvents: 'none' to the overlay style object. Working example.

@parlop @austingayler for me, this just resulted in the modal becoming an empty div, for some reason. The Draggable seems to ignore its children for some reason...

share the detailed example for reactjs model dragging

Was this page helpful?
0 / 5 - 0 ratings

Related issues

leoasis picture leoasis  路  4Comments

fabien-somnier picture fabien-somnier  路  3Comments

tairy-potter picture tairy-potter  路  3Comments

phaedryx picture phaedryx  路  4Comments

jrock17 picture jrock17  路  4Comments