Duggy
Duggy

Reputation: 85

How to keep semantic-ui modal from closing when displaying different components?

I am trying to use a modal for authentication (login and register). So far I have been able to get it to display correctly and can switch from login to register component, but for some reason the modal will close after trying to switch back from register to login. I have a header that contains the trigger for the modal. Here is my code so far:

Header.js

import React, { Component } from "react";
import Login from "./Login";
import Register from "./Register";
import logo from "../assets/logo.png"
import { Modal } from "semantic-ui-react";

class Header extends Component {
  constructor(props){
super(props);
this.state = { login: true, header: "Login"}
this.handleRegister = this.handleRegister.bind(this);


  this.handleLogin = this.handleLogin.bind(this);
  }

  handleRegister = () => {
    this.setState({ login: false,
                    header: "Register"});
  }

  handleLogin = () => {
    this.setState({ login: true,
                    header: "Login"});
  }

  renderModal () {
    const showLogin = this.state.login ? (<Login handleRegister={this.handleRegister} />) : (<Register handleLogin={this.handleLogin} />);
    return (
      <Modal closeIcon onClose={this.handleLogin} size="tiny" trigger={<a className="item">Login</a>}>
        <Modal.Header style={{backgroundColor: "#005ce6", color:"white"}}>{this.state.header}</Modal.Header>
        <Modal.Content>
          {showLogin}
        </Modal.Content>
      </Modal>
    )
  }
render() {
    return (
      <div>
        <div className="ui menu hover" style={{ padding: 0}}>

          <div className="right menu">
            {this.renderModal()}
          </div>
        </div>
    </div>


    )
  }
}

export default Header;

Register.js

import React, { Component } from 'react';

class Register extends Component {
  constructor(props){
    super(props)
    this.handleLogin = this.props.handleLogin.bind(this);
  }

  render() {
    return (
      <div>
        <div>
            <form action="/auth/register" method="post" className="ui form">
            <div className="field">
              <label>First Name</label>
              <input type="text" placeholder="First Name" name="firstName"/>
            </div>
            <div className="field">
              <label>Last Name</label>
              <input type="text" placeholder="Last Name" name="lastName"/>
            </div>
            <div className="field">
              <label>Email</label>
              <input type="text" placeholder="Email" name="email"/>
            </div>
            <div className="field">
              <label>Password</label>
              <input type="password" placeholder="Password" name="password"/>
            </div>
            <button type="submit" className="ui button">Submit</button>
            </form>
            <div style={{paddingTop:20}}>
              <div>Already have account? Please <a onClick={this.handleLogin}>Login</a></div>
            </div>
        </div>
      </div>
    )
  }
}

export default Register;

Login.js

import React, { Component } from 'react'

class Login extends Component {
  constructor(props){
    super(props)
    this.handleRegister = this.props.handleRegister.bind(this);
  }
  render(){
    return (
      <div>
          <form action="/auth/login" method="post" className="ui form">
            <div className="field">
              <label>Email</label>
              <input type="text" placeholder="Email" name="email"/>
            </div>
            <div className="field">
              <label>Password</label>
              <input type="password" placeholder="Password" name="password"/>
            </div>
            <button type="submit" className="ui button">Submit</button>
          </form>
          <div style={{paddingTop:20}}>
            <div>Don't have an account? Please <a onClick={this.handleRegister}>Register</a></div>
          </div>
      </div>

    )
  }
}
export default Login;

I have tried using the open field for the modal and setting a "show" state depending if the trigger is set off, but it ends up never closing. It seems that when I go from register to login components via the "Login" click it will set off a close event and I can not figure out why.

Upvotes: 2

Views: 3467

Answers (2)

amankkg
amankkg

Reputation: 5081

Workaround: add closeOnDimmerClick={false} as Modal prop.

Source: https://github.com/Semantic-Org/Semantic-UI-React/issues/2493#issuecomment-362972834

There are some issues with Modal component of Semantic UI React. Definitely.

Repro steps:

  1. https://codesandbox.io/s/30n2v379r1
  2. open modal by clicking Login (top left corner, also zoom out to see the links of modal)
  3. click Register link of the modal
  4. click Login link of the modal

Actual: modal is closed

Expected: modal is open and Register form is displayed

IMO, after changing the markup (Register form has more inputs) navigation link has new coordinates which is out of initial coords range of the modal. Therefore, clicking on this link now is treated like a clicking somewhere outside of the modal.

PS: yet another way to escape this auto-closing behavior is to make both forms markup more or less similar: for example, remove first two inputs from Register form so it looks exactly like Login form (of course, it's not the solution for topic-starter, just FYI), there are some comments in Register component on https://codesandbox.io/s/30n2v379r1

upd: issue on SUIR repo https://github.com/Semantic-Org/Semantic-UI-React/issues/2888

Upvotes: 2

MehulJoshi
MehulJoshi

Reputation: 889

Use open property, it's boolean if true will keep your modal open. demo link to keep modal open

<Modal
        trigger={<Button onClick={this.handleOpen}>Show Modal</Button>}
        open={this.state.modalOpen}
        onClose={this.handleClose}
        basic
        size='small'
      >

Upvotes: 0

Related Questions