Dynamic
Dynamic

Reputation: 55

Render a new Input field on Validating User Input

I have this login component where the user enters his user id, if its valid, the api sends a OTP to the user's phone. I want change the state of the input field after validation and accept the otp number for validation on the same page (the same input field). How can i do this ?

I want to have just one input field, where you enter user id after validating user id lets have the user enter password in the same (albeit new) field instead of having 2 input fields.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';

class Login extends Component {
  constructor(props) {
    super(props);
    this.state = { value: '', authd: false, error: false };
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.deAuth = this.deAuth.bind(this);
  }
  handleChange(event) {
    this.setState({ value: event.target.value });
    event.preventDefault();
  }

  deAuth() {
    this.setState({
      authd: false,
    });
  }

  handleSubmit(event) {
    if (this.state.value != '') {
      axios
        .get(
          `https://api.appspot.com/verifyClientID/client_id=${this
            .state.value}`,
        )
        .then(res => {
          console.log(res.data.message);
          this.setState({ authd: true }); // user is authenticated
        })
        .then(axios.post('https://api.appspot.com/OTPGeneration', {
    client_id: `${this
            .state.value}`,
    }))

      event.preventDefault();
    }
  }

  render() {
    const authedForm = (this.state.authd) ? <h5 className="uk-text-center otp-sent-txt">Enter OTP that was sent to your registered mobile number.</h5>: <h5 className="uk-text-center"></h5>
    return (
      <div uk-grid>
        <img src="image/logo.png" className="logo" alt="logo" />
        <div className="uk-container">
          <img
            className="landing-image uk-align-center"
            src="image/landing2.jpg"
          />
          <h2 className="landing-text">Welcome Aboard!</h2>
        </div>

        {/*{this.state.authd && <MyModal resetAuth={this.deAuth} />}*/}

        <form
          className={`uk-align-center uk-form-width-medium ${this.state.error}`}
          onSubmit={this.handleSubmit}
        >
          <div className="uk-margin">
            <input
              className="uk-input uk-text-center"
              type="text"
              placeholder="Client ID"
              value={this.state.value}
              onChange={this.handleChange}
            />
          </div>
        </form>
        {authedForm}
        <button
          className="uk-button uk-button-primary uk-align-center login-btn"
          onClick={this.handleSubmit}
        >
          Login
        </button>

      </div>
    );
  }
}

export default Login;

Upvotes: 1

Views: 992

Answers (1)

Mayank Shukla
Mayank Shukla

Reputation: 104379

Can we render a new input field and hide the old one at the same place ?

Yes, you can use conditional rendering for that. Once user id has been verified, render different input field by checking the value of this.state.authd.

Like this:

<div className="uk-margin">
    {this.state.authd ?
        <input
            className="uk-input uk-text-center"
            type="text"
            placeholder="Client ID"
            value={this.state.value}
            onChange={this.handleChange}
        />
    :
        <input
            className="uk-input uk-text-center"
            type="otp"
            placeholder="OTP"
            value={this.state.otp}
            onChange={/**/ change function}
        />
    }
</div>

I want to have just one input field, where you enter user id after validating user id lets have the user enter password in the same field.

You can also achieve this also, but for that you need to put some conditions-

  1. Condition on value of input field, initially it will have user id, after that it will have the otp value.

  2. Condition in onChange event (if you use same function for both), which value you want to update.

Like this:

<input
    name={this.state.authd ? "otp" : "value"}
    className="uk-input uk-text-center"
    type={this.state.authd ? "number" : "text"}
    placeholder={this.state.authd ? "OTP" : "Client ID"}
    value={this.state.authd ? this.state.otp : this.state.value}
    onChange={this.handleChange}
/>

handleChange(event){
    let target = event.target;
    this.setState({
        [target.name]: target.value;
    })
}

Suggestion: In case you want to use same field, i will suggest you to use uncontrolled component, in that case you don't need to put multiple condition, once user click on submit button, use the ref to get the value entered by user.

<input
    ref={el => this.input = el}
    className="uk-input uk-text-center"
    type={this.state.authd ? "number" : "text"}
    placeholder={this.state.authd ? "OTP" : "Client ID"}
/>

Now use this.input.value to get the value of input field.

Upvotes: 1

Related Questions