react node component javascript twitter-bootstrap crud reactjs

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>&times;</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">&times;</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:

  1. Clonar el elemento modal (objeto ReactElement).
  2. Cree un elemento div e insértelo en el cuerpo del documento.
  3. Renderice el elemento modal clonado en el elemento div recién insertado.
  4. 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">&times;</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">&times;</span></button> <h4 className="modal-title">Modal title</h4> </div> <div className="modal-body"> <p>One fine body&hellip;</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''));



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">&times;</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 = $;