2

I have a react component that contains a form and a bootstrap table. The form contains a submit button that I'd like to disable if the input to the table cells fail to pass validation. I've implemented the validators, but I can't find a way to tie their result with the 'disable' property of the submit button. Following is a shorter version of the full code:

class Car extends Component {
  constructor(props) {
    super(props);
      this.handleSubmit = this.handleSubmit.bind(this);
      this.ifColumns = [
          {text: 'rowID', dataField: '_id', hidden: true},
          {text: 'Engine', dataField: 'name', sort:true, editable: false,               
              headerStyle: (colum, colIndex) => {
                  return { width: '11%', textAlign: 'left' };
              },
              validator: engineValidator
      }
  }
  render()
  {
    return(         
      <div className="col-md-7">
        <Card id='updCarCard'>
          <CardBody>
            <Form model="updCar" onSubmit={(values) => 
              this.handleSubmit(values)}>
                <Row className="form-group">
                  <Label htmlFor="name" md={3}>Car Name</Label>
                  <Col md={9}>
                    <Control.text model=".name" id="name" name="name" placeholder="Car Name" 
                      component={TextInput} withFieldValue
                      validators={
                        {   
                          maxLength: maxLength(15)
                        }
                      }
                    />
                    <Errors className="text-danger" model=".name" show="touched" 
                      messages={
                        {   
                          maxLength: 'Length must be at most 15'
                        }
                      }
                    />
                  </Col>
                </Row>
                <Row className="form-group">
                  <Col md={{size:10, offset: 3}}>
                    <Control.button model="updDevice" disabled={{ valid: false }} className="btn">Update Car</Control.button>
                  </Col>
                <div className="col-md-12">
                  <BootstrapTable striped hover condensed
                    keyField='_id' 
                    data={...}  
                    columns={ this.ifColumns }
                    defaultSorted={[{dataField: 'name',order: 'asc'}] } 
                    cellEdit={ cellEditFactory({ mode: 'click', blurToSave: true }) }/>
                </div>

              </Form>
            </CardBody>
          </Card>
        </div>
  }
}

The code for TextInput:

export const TextInput = ({withFieldValue, fieldValue, ...props}) => {
  const textClassesNames = ["form-control"];
  console.log("Inside: " + JSON.stringify(fieldValue));
  if (fieldValue.touched) {
    if (fieldValue.valid) textClassesNames.push("is-valid");
    else textClassesNames.push("is-invalid");
  }
  return(
    <input className={textClassesNames.join(" ")} {...props} />
  )
}

Any ideas on how can I use the result of the table validation to control the 'disable' property of the submit button?

omer
  • 1,242
  • 4
  • 18
  • 45

1 Answers1

1

Because you didn't provide any code, I suppose you need to add a validation state for the submit button button.

// add disabled state which true on validation success.
<Control.button model="updDevice" disabled={disabled} className="btn">Update Car</Control.button>

For example:

const VALIDATION = 'hello';

function ValidateForm() {
  const [value, setValue] = useState('');
  const [disabled, setDisabled] = useState(true);
  return (
    <>
      <input
        value={value}
        onChange={e => {
          const currValue = e.target.value;
          setValue(currValue);
          if (currValue === VALIDATION) {
            setDisabled(prev => !prev);
          }
        }}
      />
      <button disabled={disabled}>submit</button>
    </>
  );
}

As for react-bootsrap same example:

const VALIDATION = 'hello';

function ValidateBootstrapForm() {
  const [value, setValue] = useState('');
  const [disabled, setDisabled] = useState(true);
  return (
    <div className="form">
      <Form>
        <Form.Group controlId="formBasicEmail">
          <Form.Control
            value={value}
            onChange={e => {
              const currValue = e.target.value;
              setValue(currValue);
              if (currValue === VALIDATION) {
                setDisabled(prev => !prev);
              }
            }}
            placeholder="Enter Hello"
          />
        </Form.Group>
        <Button disabled={disabled} variant="primary" type="submit">
          Submit
        </Button>
      </Form>
    </div>
  );
}

Demo:

Edit SO-Q-56517598

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • Added some code, so you can take a look and maybe change your answer. – omer Jun 09 '19 at 20:38
  • The answer is the same, you missing ‘this.handleSubmit’ and add a state for the validation button in your card component. See the example you should figure it out. Moreover you dont control the state of ‘TextInput’ – Dennis Vash Jun 09 '19 at 21:49
  • I don't want to run form validation upon hitting the submit button. As you can see in the code, the fields are assigned with dedication validators that run when the field is changed. The user can see that the form contains invalid input, I just want to disable the button as well. – omer Jun 10 '19 at 03:54
  • @omer I updated the answer and the demo with bootstrap `Form`. – Dennis Vash Jun 10 '19 at 10:00