javascript - node - react crud generator
Bootstrap modal en React.js (9)
Creé esta función:
onAddListItem: function () {
var Modal = ReactBootstrap.Modal;
React.render((
<Modal title=''Modal title'' onRequestHide={this.hideListItem}>
<ul class="list-group">
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
</ul>
</Modal>
), document.querySelector(''#modal-wrapper''));
}
Y luego lo usé en mi gatillo de botón.
Para ''ocultar'' el modal:
hideListItem: function () {
React.unmountComponentAtNode(document.querySelector(''#modal-wrapper''));
},
Necesito abrir un Bootstrap Modal haciendo clic en un botón en una barra de navegación de Bootstrap y en otros lugares ( para mostrar datos para una instancia de componente, es decir, proporcionar funcionalidad de "edición" ), pero no sé cómo lograr esto. Aquí está mi código:
EDITAR: Código actualizado.
ApplicationContainer = React.createClass({
render: function() {
return (
<div className="container-fluid">
<NavBar />
<div className="row">
<div className="col-md-2">
<ScheduleEntryList />
</div>
<div className="col-md-10">
</div>
</div>
<ScheduleEntryModal />
</div>
);
}
});
NavBar = React.createClass({
render: function() {
return (
<nav className="navbar navbar-default navbar-fixed-top">
<div className="container-fluid">
<div className="navbar-header">
<a className="navbar-brand" href="#">
<span className="glyphicon glyphicon-eye-open"></span>
</a>
</div>
<form className="navbar-form navbar-left">
<button className="btn btn-primary" type="button" data-toggle="modal" data-target="#scheduleentry-modal">
<span className="glyphicon glyphicon-plus">
</span>
</button>
</form>
<ul className="nav navbar-nav navbar-right">
<li><a href="#"><span className="glyphicon glyphicon-user"></span> Username</a></li>
</ul>
</div>
</nav>
);
}
});
ScheduleEntryList = React.createClass({
getInitialState: function() {
return {data: []}
},
loadData: function() {
$.ajax({
url: "/api/tasks",
dataType: "json",
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, error) {
console.error("/api/tasks", status, error.toString());
}.bind(this)
});
},
componentWillMount: function() {
this.loadData();
setInterval(this.loadData, 20000);
},
render: function() {
items = this.state.data.map(function(item) {
return <ScheduleEntryListItem item={item}></ScheduleEntryListItem>;
});
return (
<div className="list-group">
<a className="list-group-item active">
<h5 className="list-group-item-heading">Upcoming</h5>
</a>
{items}
</div>
);
}
});
ScheduleEntryListItem = React.createClass({
openModal: function() {
$("#scheduleentry-modal").modal("show");
},
render: function() {
deadline = moment(this.props.item.deadline).format("MMM Do YYYY, h:mm A");
return (
<a className="list-group-item" href="#" onClick={this.openModal}>
<h5 className="list-group-item-heading">
{this.props.item.title}
</h5>
<small className="list-group-item-text">
{deadline}
</small>
</a>
);
}
});
Modal = React.createClass({
componentDidMount: function() {
$(this.getDOMNode())
.modal({backdrop: "static", keyboard: true, show: false});
},
componentWillUnmount: function() {
$(this.getDOMNode())
.off("hidden", this.handleHidden);
},
open: function() {
$(this.getDOMNode()).modal("show");
},
close: function() {
$(this.getDOMNode()).modal("hide");
},
render: function() {
return (
<div id="scheduleentry-modal" className="modal fade" tabIndex="-1">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal">
<span>×</span>
</button>
<h4 className="modal-title">{this.props.title}</h4>
</div>
<div className="modal-body">
{this.props.children}
</div>
<div className="modal-footer">
<button type="button" className="btn btn-danger pull-left" data-dismiss="modal">Delete</button>
<button type="button" className="btn btn-primary">Save</button>
</div>
</div>
</div>
</div>
)
}
});
ScheduleEntryModal = React.createClass({
render: function() {
var modal = null;
modal = (
<Modal title="Add Schedule Entry">
<form className="form-horizontal">
<div className="form-group">
<label htmlFor="title" className="col-sm-2 control-label">Title</label>
<div className="col-sm-10">
<input id="title" className="form-control" type="text" placeholder="Title" ref="title" name="title"/>
</div>
</div>
<div className="form-group">
<label htmlFor="deadline" className="col-sm-2 control-label">Deadline</label>
<div className="col-sm-10">
<input id="deadline" className="form-control" type="datetime-local" ref="deadline" name="deadline"/>
</div>
</div>
<div className="form-group">
<label htmlFor="completed" className="col-sm-2 control-label">Completed</label>
<div className="col-sm-10">
<input id="completed" className="form-control" type="checkbox" placeholder="completed" ref="completed" name="completed"/>
</div>
</div>
<div className="form-group">
<label htmlFor="description" className="col-sm-2 control-label">Description</label>
<div className="col-sm-10">
<textarea id="description" className="form-control" placeholder="Description" ref="description" name="description"/>
</div>
</div>
</form>
</Modal>
);
return (
<div className="scheduleentry-modal">
{modal}
</div>
);
}
});
Se agradecen otros comentarios y mejoras al código.
Gracias a @tgrrr por una solución simple, especialmente cuando no se necesita una biblioteca de terceros (como React-Bootstrap). Sin embargo, esta solución tiene un problema: el contenedor modal está incrustado dentro del componente de reacción, lo que conduce a un problema modal bajo fondo cuando el componente de reacción externo (o su elemento padre) tiene un estilo de posición como fijo / relativo / absoluto. Encontré este problema y encontré una nueva solución:
//Modal component
import React, { Component } from ''react'';
export const ModalHeader = props => {
return <div className="modal-header">{props.children}</div>;
};
export const ModalBody = props => {
return <div className="modal-body">{props.children}</div>;
};
export const ModalFooter = props => {
return <div className="modal-footer">{props.children}</div>;
};
class Modal extends Component {
constructor(props) {
super(props);
this.state = {
modalShow: '''',
display: ''none''
};
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
}
openModal() {
this.setState({
modalShow: ''show'',
display: ''block''
});
}
closeModal() {
this.setState({
modalShow: '''',
display: ''none''
});
}
componentDidMount() {
this.props.isOpen ? this.openModal() : this.closeModal();
}
componentDidUpdate(prevProps) {
if (prevProps.isOpen !== this.props.isOpen) {
this.props.isOpen ? this.openModal() : this.closeModal();
}
}
render() {
return (
<div
className={''modal fade '' + this.state.modalShow}
tabIndex="-1"
role="dialog"
aria-hidden="true"
style={{ display: this.state.display }}
>
<div className="modal-dialog" role="document">
<div className="modal-content">{this.props.children}</div>
</div>
</div>
);
}
}
export default Modal;
//App component
import React, { Component } from ''react'';
import Modal, { ModalHeader, ModalBody, ModalFooter } from ''./components/Modal'';
import ''./App.css'';
class App extends Component {
constructor(props) {
super(props);
this.state = {
modal: false
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({ modal: !this.state.modal });
}
render() {
return (
<div className="App">
<h1>Bootstrap Components</h1>
<button
type="button"
className="btn btn-secondary"
onClick={this.toggle}
>
Modal
</button>
<Modal isOpen={this.state.modal}>
<ModalHeader>
<h3>This is modal header</h3>
<button
type="button"
className="close"
aria-label="Close"
onClick={this.toggle}
>
<span aria-hidden="true">×</span>
</button>
</ModalHeader>
<ModalBody>
<p>This is modal body</p>
</ModalBody>
<ModalFooter>
<button
type="button"
className="btn btn-secondary"
onClick={this.toggle}
>
Close
</button>
<button
type="button"
className="btn btn-primary"
onClick={this.toggle}
>
Save changes
</button>
</ModalFooter>
</Modal>
</div>
);
}
}
export default App;
La idea principal es:
- Clonar el elemento modal (objeto ReactElement).
- Cree un elemento div e insértelo en el cuerpo del documento.
- Renderice el elemento modal clonado en el elemento div recién insertado.
- Cuando finalice el renderizado, muestre modal. Además, adjunte un detector de eventos, de modo que cuando modal esté oculto, se elimine el elemento div recién insertado.
Puede probar este modal: https://github.com/xue2han/react-dynamic-modal No tiene estado y solo se puede representar cuando sea necesario. Por lo tanto, es muy fácil de usar. Simplemente así:
"use strict";
var React = require(''react'');
var ReactDOM = require(''react-dom'');
var SampleModal = React.createClass({
render: function() {
return (
<div className="modal fade" tabindex="-1" role="dialog">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title">Title</h4>
</div>
<div className="modal-body">
<p>Modal content</p>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" className="btn btn-primary">OK</button>
</div>
</div>
</div>
</div>
);
}
});
var sampleModalId = ''sample-modal-container'';
var SampleApp = React.createClass({
handleShowSampleModal: function() {
var modal = React.cloneElement(<SampleModal></SampleModal>);
var modalContainer = document.createElement(''div'');
modalContainer.id = sampleModalId;
document.body.appendChild(modalContainer);
ReactDOM.render(modal, modalContainer, function() {
var modalObj = $(''#''+sampleModalId+''>.modal'');
modalObj.modal(''show'');
modalObj.on(''hidden.bs.modal'', this.handleHideSampleModal);
}.bind(this));
},
handleHideSampleModal: function() {
$(''#''+sampleModalId).remove();
},
render: function(){
return (
<div>
<a href="javascript:;" onClick={this.handleShowSampleModal}>show modal</a>
</div>
)
}
});
module.exports = SampleApp;
Puede usar React-Bootstrap ( https://react-bootstrap.github.io/components/modal ). Hay un ejemplo de modales en ese enlace. Una vez que haya cargado react-bootstrap, el componente modal se puede usar como componente de reacción:
var Modal = ReactBootstrap.Modal;
entonces puede usarse como un componente de reacción como
<Modal/>
.
Para Bootstrap 4, hay react-strap ( https://reactstrap.github.io ). React-Bootstrap solo es compatible con Bootstrap 3.
Recientemente estaba buscando una buena solución para esto sin agregar React-Bootstrap a mi proyecto (ya que Bootstrap 4 está a punto de ser lanzado).
Esta es mi solución: https://jsfiddle.net/16j1se1q/1/
let Modal = React.createClass({
componentDidMount(){
$(this.getDOMNode()).modal(''show'');
$(this.getDOMNode()).on(''hidden.bs.modal'', this.props.handleHideModal);
},
render(){
return (
<div className="modal fade">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title">Modal title</h4>
</div>
<div className="modal-body">
<p>One fine body…</p>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
)
},
propTypes:{
handleHideModal: React.PropTypes.func.isRequired
}
});
let App = React.createClass({
getInitialState(){
return {view: {showModal: false}}
},
handleHideModal(){
this.setState({view: {showModal: false}})
},
handleShowModal(){
this.setState({view: {showModal: true}})
},
render(){
return(
<div className="row">
<button className="btn btn-default btn-block" onClick={this.handleShowModal}>Open Modal</button>
{this.state.view.showModal ? <Modal handleHideModal={this.handleHideModal}/> : null}
</div>
);
}
});
React.render(
<App />,
document.getElementById(''container'')
);
La idea principal es renderizar solo el componente modal en React DOM cuando se va a mostrar (en la función de renderización de componentes de la aplicación). Mantengo un estado de "vista" que indica si el modal se muestra actualmente o no.
Las devoluciones de llamada ''componentDidMount'' y ''componentWillUnmount'' ocultan o muestran el modal (una vez que se procesa en React DOM) a través de las funciones de JavaScript de Bootstrap.
Creo que esta solución sigue muy bien el espíritu de React, ¡pero las sugerencias son bienvenidas!
Simplemente agregue
href=''#scheduleentry-modal''
al elemento con el que desea abrir el modal con
O usando jQuery:
$(''#scheduleentry-modal'').modal(''show'');
Solo he usado bootstrap cdn (css + js) para lograr una solución similar a "reactstrap". He usado props.children para pasar datos dinámicos de componentes primarios a secundarios. Puedes encontrar más sobre esto here . De esta manera, tiene tres componentes separados: encabezado modal, cuerpo modal y pie de página modal, y son totalmente independientes entre sí.
class MyModal extends Component{
render(){
const { text } = this.props;
return (
<Modal
onRequestClose={this.props.onRequestClose}
openTimeoutMS={150}
closeTimeoutMS={150}
style={customStyle}>
<h1>What you input : {text}</h1>
<button onClick={ModalManager.close}>Close Modal</button>
</Modal>
);
}
}
class App extends Component{
openModal(){
const text = this.refs.input.value;
ModalManager.open(<MyModal text={text} onRequestClose={() => true}/>);
}
render(){
return (
<div>
<div><input type="text" placeholder="input something" ref="input" /></div>
<div><button type="button" onClick={this.openModal.bind(this)}>Open Modal </button> </div>
</div>
);
}
}
ReactDOM.render(<App />,document.getElementById(''main''));
Reactstrap también tiene una implementación de Bootstrap Modals en React . Esta biblioteca se dirige a Bootstrap versión 4, mientras que react-bootstrap se dirige a la versión 3.X.
getDOMNode()
está en desuso.
En su lugar, use
ref
para acceder al elemento DOM.
Aquí está trabajando el componente modal (Bootstrap 4).
Decida si desea mostrar o no el componente modal en el componente principal.
Ejemplo: https://jsfiddle.net/sqfhkdcy/
class Modal extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
$(this.modal).modal(''show'');
$(this.modal).on(''hidden.bs.modal'', handleModalCloseClick);
}
render() {
return (
<div>
<div className="modal fade" ref={modal=> this.modal = modal} id="exampleModal" tabIndex="-1" role="dialog" aria- labelledby="exampleModalLabel" aria-hidden="true">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLabel">Modal title
</h5>
<button type="button" className="close" data- dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-body">
...
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" data- dismiss="modal">Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
Editar:
Aquí están las importaciones necesarias para que funcione:
import $ from ''jquery'';
window.jQuery = $;
window.$ = $;
global.jQuery = $;