Search code examples
javascriptreactjsreactstrap

I have a validate function in React/Reactstrap which I'm applying to multiple fields, however all fields are validating at the same time


Here's my code so far (just the relevant parts, and I'm also using availity-reactstrap-validation just FYI):

export default class CustomModal extends Component {
    constructor(props) {
        super(props);
        this.state = {
            data: [],
            toolPlatform: [],
            workstream: [],
            opsarea: [],
            campus: [],
            riskcat: [],
            activeItem: this.props.activeItem,
        validate: {
            textState: '',
        },
        };
    }

validateText(e) {
        const textRex = /^(?!\s*$).+/;
        const { validate } = this.state
            if (textRex.test(e.target.value)) {
                validate.textState = 'has-success'
            } else {
                validate.textState = 'has-danger'
            }
            this.setState( {validate})
        };


render() {
        const { toggle, onSave } = this.props;
        return (            
            <Modal isOpen={true} toggle={toggle}>
                <ModalHeader toggle={toggle}> Tool Details </ModalHeader>
                <ModalBody>
                    <AvForm onValidSubmit = {() => onSave(this.state.activeItem)}>
                        <FormGroup>
                            <Label for="title">Title</Label>
                            <AvInput valid 
                                type="text"
                                name="title"
                                value={this.state.activeItem.title}
                                //onChange={this.handleChange}
                                placeholder="Tool Name"
                                valid={ this.state.validate.textState === 'has-success' }
                                invalid={ this.state.validate.textState === 'has-danger' }
                                onChange={ (e) => {
                                    this.validateText(e)
                                    this.handleChange(e)
                                }}
                                required
                            />
                        </FormGroup> 
                        <AvGroup>
                            <Label for="description">Description</Label>
                            <AvInput valid
                                type="text"
                                name="description"
                                value={this.state.activeItem.description}
                                valid={ this.state.validate.textState === 'has-success' }
                                invalid={ this.state.validate.textState === 'has-danger' }
                                placeholder="Tool description"
                                onChange={ (e) => {
                                    this.validateText(e)
                                    this.handleChange(e)
                                }}
                                required
                            />

The validation works, however when I start typing in one of the fields, both fields are validated at the same time. This makes sense, and I get why it's doing it, but I'm not 100% sure how to change the syntax to only validate the fields I'm typing in.

Hope that makes sense! I'm sure it's fairly basic to change, I'm just new, and learning, so I can't quite get the right syntax.

Thanks a lot!


Solution

  • First, you need two different fields for your textState, otherwise they share the same:

    this.state = {
            data: [],
            toolPlatform: [],
            workstream: [],
            opsarea: [],
            campus: [],
            riskcat: [],
            activeItem: this.props.activeItem,
            validate: {
                textState: {
                    title: '',
                    description: '',
                },
            },
        };
    

    Then check e.target.name to determine which field of textState to update (you could also pass it as an argument in this function)

    validateText ( e ) {
        const textRex = /^(?!\s*$).+/; 
    
        // If test is true / false
        const fieldTextState = textRex.test( e.target.value ) ? 'has-success' : 'has-danger'
    
        // Create textState object with all the fields
        const textState = Object.assign( {}, this.state.validate.textState, { [ e.target.name ]: fieldTextState})
    
        this.setState( { validate : { textState  } } )
    };
    

    Also, set specific valid and invalid for each input

                             <AvInput valid
                                type="text"
                                name="title"
                                value={ this.state.activeItem.title }
                                //onChange={this.handleChange}
                                placeholder="Tool Name"
                                valid={ this.state.validate.textState.title === 'has-success' }
                                invalid={ this.state.validate.textState.title === 'has-danger' }
                                onChange={ ( e ) => {
                                    this.validateText( e )
                                    this.handleChange( e )
                                } }
                                required
                            />
    

    and

                            <AvInput valid
                                type="text"
                                name="description"
                                value={ this.state.activeItem.description }
                                valid={ this.state.validate.textState.description === 'has-success' }
                                invalid={ this.state.validate.textState.description === 'has-danger' }
                                placeholder="Tool description"
                                onChange={ ( e ) => {
                                    this.validateText( e )
                                    this.handleChange( e )
                                } }
                                required
                            />