使用门户动态创建React模式

时间:2017-12-19 19:54:20

标签: javascript reactjs modal-dialog

如何使用嵌套门户将组件附加到模态?

我正在构建一个显示多个模态的页面。我想重用相同的模态但是当单击一个按钮时,应用程序会将不同的内容加载到模态中。

WIP CodePen:

https://codepen.io/jtsharpsite/pen/gorvjR

 render() {
  return ReactDOM.createPortal(
   this.props.children,
   domNode,
  );
 }

我非常接近我认为可行的方式,但我无法弄清楚如何将另一个组件附加到已经附加的模态组件。

我有一个按钮,它调用打开模态的处理程序并指定组件类型。

<button onClick={this.handleShow.bind(this, "p3009", "product")}>
      Product 3009
</button>

<button onClick={this.handleShow.bind(this, "s1", "special")}>
      Special #1
</button>

处理程序位于App上下文中并打开模态兄弟:

handleShow(modalId, modalType) {    
     this.setState({ showModal: true });
}

当模态组件安装完毕后,我会尝试在安装时附加产品。

componentDidMount() {
   //TODO how to append to parent modal?
   modalRoot.appendChild(this.el);
}

如何将 <Product> <Special> 移至 <Modal>

2 个答案:

答案 0 :(得分:0)

您是否尝试在门户网站中使用父子模式。

例如,让你的孩子像这样,让ModalDisplay呈现它的孩子。我不知道你想要做什么是可能的,因为我认为它需要门户网站来支持片段,我不确定它们是否会这样做。

我不知道我的问题背景是否正确但是你的想法是一样的,你有一个孩子本身有孩子,而不是在门户网站电话中有超过1个孩子。

<ModalDisplay>
  <Special title="special" text="text" />

  <Product title="product" pic="picture" />
</ModalDisplay>

答案 1 :(得分:0)

这是一个可重复使用的模态形式的例子......这里有很多你不需要的东西,但只需要注意handleSubmit。在handleSubmit中我们调用onComplete(),它可以是我们调用它时传递给可重用模式的任何函数,基于我们希望我们的模态执行的函数...在我们的例子中它是捕获用户名,密码等。

class ReusableModalForm extends React.Component {
  constructor(props){
    super(props);
    this.state ={
    };
  }



  handleChange(e) {
   let {name, value} = e.target;
   this.setState({
     [name]: value,
     usernameError: name === 'username' && !value ? 'username must have a value' : null,
     emailError: name === 'email' && !value ? 'email must have a value' : null,
     passwordError: name === 'password' && !value ? 'password must have a value' : null,
   });


 }

 handleSubmit(e) {
   e.preventDefault();
   this.props.onComplete(this.state)
 }

  render() {

    return (
     <Modal
       open={this.state.createAccountModalOpen}
       trigger={<Link size="m" theme="bare" href="#" className="main-menu-item" onClick={this.handleSubmit}>{this.props.buttonText}</Link>}
       closeIcon
       onClose={() => { this.setState({
           createAccountModalOpen: false,
       }); }}
   >
       <Header icon='add user' content='Create account' />
       <Modal.Content>
           <Form />
       </Modal.Content>
       <Modal.Actions>
           <Button color='green' onClick={this.handleSubmit}>
               <Icon name='add user' /> {this.props.buttonText}
           </Button>
       </Modal.Actions>
   </Modal>
    );
  }
}



export default ReusableModalForm;

基于这个逻辑,你可以构造一个带有一系列“触发器文本”的模态,只根据你使用可重用模态时传递的道具类型来渲染某些东西。

实施例。

<ReusableModal triggerText={'showAdress'} onComplete={this.showUsersHomeOnGoogle} />

然后在你的reusableModal某处......

{this.props.triggerText === showAdress ? this.setState=({showHomeAdressPortion: true)}

更新

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { showModal: false };

    this.handleShow = this.handleShow.bind(this);
    this.handleHide = this.handleHide.bind(this);
  }

  handleShow(modalId, modalType) {
    console.log(
      "Append content with ID: " + modalId + " of component type: " + modalType
    );
    //Here you should do a "fetch" first and grab your entire product information based on chosen ID and store it to state as an object...
    //setState({activePortal: someContentObject})
    //Then... I would use promise or aync await, show modal...
    //Have Modal display from this state object
    this.setState({ showModal: true, activePortal:  });

    //if it is a product
    if (modalType == "product") {
      //fetch additional images and add to state
      //add images to {product.additionalPics}
    }

    //TODO re-render the modal with the appending element portal
  }

  handleHide() {
    this.setState({ showModal: false });
  }

  render() {
    //console.log("RENDER App");

    // Show a Modal on click.
    const modal = this.state.showModal ? (
      <Modal>
        <div className="modal">
          <div className="modal-content-wrapper">
            {/* I think what you're asking to do here is display basically "any" information that comes from a product fetch. This isnt possible without templeting somehow.. You will have to hard code like "title" "body" "image" into this modal...
            <h1>this.state.activeProduct.title</h1>*/}
            {/* CONTENT NEEDS TO GO HERE SOMEHOW */}
            {this.props.children}
          </div>

          <button onClick={this.handleHide}>Hide modal</button>
        </div>
      </Modal>
    ) : null;