Ashish Bairwa
Ashish Bairwa

Reputation: 775

Adding a specific validation to a component in ReactJS

I have a component class which makes a field editable. I want to add it to a field named date of birth and for this i have added it in my view component. My date is coming in a specific format and i have made a function named check date for that. I want to make this function in such a way so that it stop the textbox until the date specified in it is in the valid format (DD-MMM-YYYY). I'm not sure how to stop it from submitting the values or how to loop it till the check is complete and then submit the value? I've made the changes on handleClick(), is there any specific position where i should make the changes so that it will work? My changes right now submitting the values and is not working as expected.

import React, { Component } from 'react';
import { Icon, Input, Dropdown } from 'semantic-ui-react';
import moment from 'moment';
import { sendNotification } from '../../helpers/Common';


const checkDate = (date) => {
  if(moment(date, 'DD-MMM-YYYY', true).isValid()){
    return moment(date, 'DD-MMM-YYYY').format('YYYYMMDD');
  } else {
    sendNotification({
      message: 'Invalid date input, please provide date in valid format (DD-MMM-YYYY)',
      kind: 'danger',
      dismissAfter: 2600
    });
    return date;
  }
}
export default class EditableItem extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isEditable: false,
      isHovered: false,
      itemValue: this.props.itemValue,
    };
    this.handleClick = this.handleClick.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.updatePatientSex = this.updatePatientSex.bind(this);
  }

  handleClick(e) {
    e.stopPropagation();
    let itemName = this.props.itemName;
    let params = {
      id: this.props.studyId,
    };
    if (itemName === 'users') {
      params['userInfo'] = {
        name: this.state.itemValue
      };
    } else if(itemName === 'birthDate') {
      params['userInfo'] = {
        birthDate: checkDate(this.state.itemValue)
      };
    } else {
      params[itemName] = this.state.itemValue;
    }
    this.props.updateItem(params);
    this.setState({ isEditable: false, isHovered: false });
  }

  handleChange(e) {
    if (this.props.itemName === 'age')
      this.setState({ itemValue: e.target.value.match(/[0-9]*/)[0] });
    else this.setState({ itemValue: e.target.value });
  }

  componentDidMount() {
    this.setState({
      itemValue: this.props.itemValue
    });
  }
  UNSAFE_componentWillReceiveProps(newProps) {
    let itemValue = this.state.itemValue;
    if (this.state.itemValue !== newProps.itemValue) {
      itemValue = newProps.itemValue;
    }
    this.setState({ itemValue, isEditable: false, isHovered: false });
  }

  render() {
    let genderIcon = '';
    if (this.props.itemName === 'sex') {
      switch (this.state.itemValue) {
        case 'male':
          genderIcon = 'male';
          break;
        case 'female':
          genderIcon = 'female';
          break;
        case 'unisex':
          genderIcon = 'intersex';
          break;
        default:
          genderIcon = 'circle outline';
      }
    }
    const allowRadEditable = this.props.allowRadEditable !== 'non-editable';
    return (
      <>
        {!this.state.isEditable && <span className={`${allowRadEditable ? "displayedValue " : ''}` + this.props.itemName} onMouseEnter={() => { this.setState({ isHovered: true }); }} onMouseLeave={() => { this.setState({ isHovered: false }); }}>
          {this.props.itemName === 'sex' && <Icon className={genderIcon === "circle outline " ? genderIcon + " small" : genderIcon} />}
          {this.props.itemName !== 'sex' && ((this.state.itemValue) ? "  " + this.state.itemValue : '-')}
          {allowRadEditable ? (this.state.isHovered || this.props.source === 'templates') && <Icon size="small" onClick={(e) => { e.stopPropagation(); this.setState({ isEditable: true }); }} className={"editableItem pencil " + this.props.itemName} /> : ''}
        </span>}
        {this.props.isEditable}
        {this.state.isEditable && (
          (this.props.dropdown === 'true') ?
            this.props.itemName === 'sex' &&
              (allowRadEditable) ?
              <Dropdown text={<Icon className={`${genderIcon === "circle outline " ? genderIcon + 'small' : genderIcon} removeSpace`} />} className="editableInput" open={this.state.isEditable}>
                <Dropdown.Menu>
                  <Dropdown.Item className="genderItem male" key="male" icon="male" value="male" onClick={this.updateSex} title="Male" content="Male" />
                  <Dropdown.Item className="genderItem female" key="female" icon="female" value="female" onClick={this.updateSex} title="Female" content="Female" />
                  <Dropdown.Item className="genderItem other" key="other" icon={<Icon name="circle outline" size="small" />} value="other" onClick={this.updateSex} title="Other" content="Other" />
                  {this.props.source === 'templates' &&
                    <Dropdown.Item className="genderItem unisex" key="unisex" icon="intersex" value="unisex" onClick={this.updatePatientSex} title="Unisex" content="Unisex" />}
                </Dropdown.Menu>
              </Dropdown> :
              <Icon className={(genderIcon === "circle outline" ? genderIcon + " small" : genderIcon) + " removeSpace"} />
            :
            <Input size='mini' id="textInput"
              onChange={(e) => { this.handleChange(e); }}
              maxLength={this.props.itemName === 'age' ? "3" : undefined}
              value={this.state.itemValue}
              onClick={(e) => { e.stopPropagation(); }}
              icon={{ name: 'check', link: true, onClick: (e) => this.handleClick(e) }} />
        )}
      </>
    );
  }
}

Upvotes: 0

Views: 39

Answers (1)

Ashish Bairwa
Ashish Bairwa

Reputation: 775

Changes have to be made in the handleChange section of the code:

  handleChange(e) {
    if (this.props.itemName === 'age')
      this.setState({ itemValue: e.target.value.match(/[0-9]*/)[0] });
    else if (this.props.itemName === 'birthDate'){
      if ((moment(e.target.value, ['DD-MMM-YYYY', 'DD-MM-YYYY'], true).isValid())){
        this.setState({ isDisabled: false, itemValue: e.target.value });
      }
      else {
        this.setState({ isDisabled: true, itemValue: e.target.value });
      }
    }
    else this.setState({ itemValue: e.target.value });
  }

A new state was created, which will toggle and enable the button only when the date is in valid format. An array was provided to moment's method which contains the allowed formats and then isValid() was called to return a boolean for validity.

Upvotes: 0

Related Questions