Reputation: 31
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!
Upvotes: 2
Views: 2613
Reputation: 8178
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>
Upvotes: 3