简体   繁体   中英

Reusable modal in ReactJs

I'm trying to create a service which will show a Confirm Dialog and catch user's action (Confirm/Cancel) and can be reusable in any Component with less attempt.

What I tried so far (using React gateway to inject my Dialog)

I create a service like:

var createConfirm = function(options, onConfirm, onCancel) {
  options = options || {};
  var actions = [
    <FlatButton
      label="Cancel"
      primary={true}
      onClick={onCancel}
    />,
    <RaisedButton
      label="OK"
      primary={true}
      onClick={onConfirm}
    />,
  ];
  return (
    <Gateway into="confirm-modal">
      <Dialog
        title={options.title || 'Confirmation'}
        actions={actions}
        modal={true}
        open={true}
      >
        {options.content || 'Are you sure?'}
      </Dialog>
    </Gateway>
  )
}

export default createConfirm;

Then in my component, I inject this to render() function:

...
{
   _this.state.isOpen && _this.confirmable
}

And whenever I need to show Confirm modal, I'll call

this.confirmable = createConfirm({
  title: 'CONFIRM',
  content: 'Are you sure to do that'
}, function() {
  console.log('user confirm')
  _this.setState({
    isOpen: false
  });
}, function() {
  console.log('user cancel')
  _this.setState({
    isOpen: false
  })
});
this.setState({isOpen: true});

My problem

What I do to close that Confirm dialog, as you can see, is set isOpen state to false so it won't be rendered. It's a little cheat and seems not a native way to close a Dialog (lose leaving animation, look weird ...).

So how can I implement a service where I have full control to the Dialog?

Thank you!

 var Modal = React.createClass({ displayName: 'Modal', backdrop: function() { return <div className='modal-backdrop in' />; }, modal: function() { var style = {display: 'block'}; return ( <div className='modal in' tabIndex='-1' role='dialog' aria-hidden='false' ref='modal' style={style} > <div className='modal-dialog'> <div className='modal-content'> {this.props.children} </div> </div> </div> ); }, render: function() { return ( <div> {this.backdrop()} {this.modal()} </div> ); } }); var Confirm = React.createClass({ displayName: 'Confirm', getDefaultProps: function() { return { confirmLabel: 'OK', abortLabel: 'Cancel' }; }, abort: function() { return this.promise.reject(); }, confirm: function() { return this.promise.resolve(); }, componentDidMount: function() { this.promise = new $.Deferred(); return React.findDOMNode(this.refs.confirm).focus(); }, render: function() { var modalBody; if (this.props.description) { modalBody = ( <div className='modal-body'> {this.props.description} </div> ); } return ( <Modal> <div className='modal-header'> <h4 className='modal-title'> {this.props.message} </h4> </div> {modalBody} <div className='modal-footer'> <div className='text-right'> <button role='abort' type='button' className='btn btn-default' onClick={this.abort} > {this.props.abortLabel} </button> {' '} <button role='confirm' type='button' className='btn btn-primary' ref='confirm' onClick={this.confirm} > {this.props.confirmLabel} </button> </div> </div> </Modal> ); } }); var confirm = function(message, options) { var cleanup, component, props, wrapper; if (options == null) { options = {}; } props = $.extend({ message: message }, options); wrapper = document.body.appendChild(document.createElement('div')); component = React.render(<Confirm {...props}/>, wrapper); cleanup = function() { React.unmountComponentAtNode(wrapper); return setTimeout(function() { return wrapper.remove(); }); }; return component.promise.always(cleanup).promise(); }; $(function() { return $('.removable').click(function() { return confirm('Are you sure?', { description: 'Would you like to remove this item from the list?', confirmLabel: 'Yes', abortLabel: 'No' }).then((function(_this) { return function() { return $(_this).parent().remove(); }; })(this)); }); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/react-with-addons.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/JSXTransformer.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <div id="row"> <div class="well"> <ul> <li>Foo <a href="#" class="removable"><i class="glyphicon glyphicon-trash"></i></a></li> <li>Bar <a href="#" class="removable"><i class="glyphicon glyphicon-trash"></i></a></li> <li>Baz <a href="#" class="removable"><i class="glyphicon glyphicon-trash"></i></a></li> </ul> </div> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM