availity-reactstrap-validation icon indicating copy to clipboard operation
availity-reactstrap-validation copied to clipboard

How to access the errorMessage within an AvGroup?

Open amillward opened this issue 5 years ago • 5 comments

Hi,

I'm adding this library to my project, but can't see how to access the errorMessage without using AvField ? (I don't want to use AvField because I have a layout to preserve)

<AvGroup>
  <InputGroup size="sm">
    <InputGroupAddon addonType="prepend">
      <span className="input-group-text">&gt;100</span>
    </InputGroupAddon>
    <AvInput
      type="number"
      name="myNumber"
      value={numAvaility}
      validate={{
        min: {
          value: 100,
          errorMessage: "Must be over 100"
        }
      }}
      onChange={e => setNumAvaility(e.target.value)}
    />
    <AvFeedback>How do I get this message?</AvFeedback>
  </InputGroup>
</AvGroup>

Codesandbox here: https://codesandbox.io/s/broken-smoke-jpbgy

amillward avatar Jul 20 '19 16:07 amillward

You'd have to get getInputState from the FormCtrl context and call it with the specific field's name: FormCtrl.getInputState('myNumber') to get back the validation object which contains errorMessage.

<AvGroup>
  <InputGroup size="sm">
    <InputGroupAddon addonType="prepend">
      <span className="input-group-text">&gt;100</span>
    </InputGroupAddon>
    <AvInput
      type="number"
      name="myNumber"
      value={numAvaility}
      validate={{
        min: {
          value: 100,
          errorMessage: "Must be over 100"
        }
      }}
      onChange={e => setNumAvaility(e.target.value)}
    />
    <AvFeedback>{this.context.FormCtrl && this.context.FormCtrl.getInputState('myNumber').errorMessage}</AvFeedback>
  </InputGroup>
</AvGroup>

AvField is a convenience component for a common layout. If you need a different layout you can basically just copy the existing AvField and modify it in your project to meet your needs.

TheSharpieOne avatar Jul 22 '19 10:07 TheSharpieOne

Alternatively @TheSharpieOne I was also thinking about making an update to allow the user to pass in a name prop on the AvFeedback and then rendering that field's error message by default via the FormCtrl.getInputState like we do for AvField. You see anything wrong with this?

GoPro16 avatar Jul 22 '19 10:07 GoPro16

Thank you @GoPro16 . How should the context be passed through? My function looks like this;

function App() {
  const [numAvaility, setNumAvaility] = useState("0");
  return (
    <AvForm>
      <Row>
        <Col xs={{ size: 5, offset: 3 }}>
          <AvGroup>
            <InputGroup size="sm">
              <InputGroupAddon addonType="prepend">
                <span className="input-group-text">&gt;100</span>
              </InputGroupAddon>
              <AvInput
                type="number"
                name="numAvaility"
                value={numAvaility}
                validate={{
                  min: {
                    value: 100,
                    errorMessage: "Must be over 100"
                  }
                }}
                onChange={e => setNumAvaility(e.target.value)}
              />
              <AvFeedback>{this.context.FormCtrl && this.context.FormCtrl.getInputState('numAvaility').errorMessage}</AvFeedback>
            </InputGroup>
          </AvGroup>
        </Col>
      </Row>
    </AvForm>
  );
}

but of course this.context wont work in functional components

amillward avatar Jul 22 '19 12:07 amillward

@GoPro16 That sounds good to me :+1:

TheSharpieOne avatar Jul 22 '19 17:07 TheSharpieOne

but of course this.context wont work in functional components

@amillward You can access Legacy Contexts in a functional component: React docs

import PropTypes from 'prop-types';

function App(props, context) {
  const [numAvaility, setNumAvaility] = useState("0");
  const validation = (context.FormCtrl) ? context.FormCtrl.getInputState("numAvaility") : {};

  return (
    <AvForm>
      <Row>
        <Col xs={{ size: 5, offset: 3 }}>
          <AvGroup>
            <InputGroup size="sm">
              <InputGroupAddon addonType="prepend">
                <span className="input-group-text">&gt;100</span>
              </InputGroupAddon>
              <AvInput
                type="number"
                name="numAvaility"
                value={numAvaility}
                validate={{
                  min: {
                    value: 100,
                    errorMessage: "Must be over 100"
                  }
                }}
                onChange={e => setNumAvaility(e.target.value)}
              />
              <AvFeedback>{validation.errorMessage || ''}</AvFeedback>
            </InputGroup>
          </AvGroup>
        </Col>
      </Row>
    </AvForm>
  );
}

App.contextTypes = {
  FormCtrl: PropTypes.object.isRequired
}

export default App;

matheusb-comp avatar Feb 15 '20 20:02 matheusb-comp