Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typing issue with FormControl onChange #2781

Closed
Alan-Hinton opened this issue Sep 4, 2017 · 6 comments
Closed

Typing issue with FormControl onChange #2781

Alan-Hinton opened this issue Sep 4, 2017 · 6 comments

Comments

@Alan-Hinton
Copy link

I'm not quite sure if this issue belongs here or on the Definitely Typed repository, but I'll try here first.

When using the FormControl in React with typescript I am forced to cast the currentTarget to any in the event handler in order to access the value of the FormControl. This gives me linter error and just seems wrong.

Either the FormControl should have a value property that can be accessed through the currentTarget or there should be an entierly new event that just passes me back the value string. The later would follow the react methodology more closely.

Here is an example of the code with the offending cast.

class MyComponent extends React.Component<Props, {}> {
  queryChange(event: React.FormEvent<FormControl>) {
    // tslint:disable-next-line:no-any  
    this.props.queryChanged((event.currentTarget as any).value);
  }

  render() {
    return (
      <div>
            <form>
              <FormGroup>
                <ControlLabel>Site</ControlLabel>
                <InputGroup>
                  <FormControl
                    type="text"
                    value={this.props.query}
                    placeholder="Search site"
                    onChange={e => this.queryChange(e)}
                  />
                </InputGroup>
              </FormGroup>
            </form>
          )}
      </div>
    );
  }
}
@jquense
Copy link
Member

jquense commented Sep 4, 2017

This seems like a TS type def issue. The event in the change handler is the unmodified React SyntheticEvent object not anything specific to react bootstrap

@taion taion closed this as completed Sep 13, 2017
@patsissons
Copy link

The main problem is that DOMAttributes<T> is using the same generic type param as ClassAttributes<T> which is technically incorrect. While it is sensible to do this for very simple components, any composite components may nor longer make any sense as you cannot presume that all DOM events are generated by the react component, instead of a sub element bubbling events up to the react component, FormControl is one of these exceptions. As these typings are defined in @types/react there is little react-bootstrap can do to mitigate this on their end.

I have come to two solutions to deal with this react typing deficiency, either aggregate sub element events within the component (using a handleBlah function pattern works well) and deal with the type variance within the internal function, or you can type your onChange parameter with a union type...

<FormControl type='text' onChange={ (x: React.FormEvent<FormControl & HTMLInputElement>) => { alert(x.currentTarget.value); } } />

The first option is probably the best option, but if you want to inline without upcasting to any then the 2nd option is handy.

@modmatic
Copy link

modmatic commented Jul 6, 2019

@patsissons Still having problems when I try the second approach:

Type '(e: FormEvent<Form<"input"> & HTMLInputElement>) => void' is not assignable to type '(event: FormEvent<ReplaceProps<"input", BsPrefixProps<"input"> & FormControlProps>>) => void'.
  Types of parameters 'e' and 'event' are incompatible.
    Type 'FormEvent<ReplaceProps<"input", BsPrefixProps<"input"> & FormControlProps>>' is not assignable to type 'FormEvent<Form<"input"> & HTMLInputElement>'.
      Type 'ReplaceProps<"input", BsPrefixProps<"input"> & FormControlProps>' is not assignable to type 'Form<"input"> & HTMLInputElement'.
        Type 'Pick<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "form" | "style" | "title" | "pattern" | "ref" | "key" | "accept" | "alt" | "autoComplete" | ... 269 more ... | "onTransitionEndCapture"> & BsPrefixProps<...> & FormControlProps' is missing the following properties from type 'Form<"input">': context, setState, forceUpdate, render, and 3 more.  TS2322

    51 |                 autoComplete="username"
    52 |                 value={this.state.email}
  > 53 |                 onChange={this.handleEmailChange}
       |                 ^
    54 |                 required
    55 |                 autoFocus
    56 |               />

My render looks like this:

render(): React.ReactNode {
    return (
      <Card className="Login-container" >
        <Card.Body>
          <Card.Title className="text-center">Admin Login</Card.Title>
          <Form onSubmit={this.handleLogin}>
            <Form.Group>
              <Form.Label>Email</Form.Label>
              <Form.Control
                type="email"
                autoComplete="username"
                value={this.state.email}
                onChange={this.handleEmailChange}
                required
                autoFocus
              />
            </Form.Group>
            <Form.Group>
              <Form.Label>Password</Form.Label>
              <Form.Control
                type="password"
                autoComplete="current-password"
                value={this.state.password}
                onChange={this.handlePasswordChange}
                required
              />
            </Form.Group>
            <Button
              className="Login-submit"
              variant="primary"
              type="submit">
              Log In
          </Button>
          </Form>
        </Card.Body>
      </Card>
    );
  }

@apieceofbart
Copy link

Is anyone looking at this now that type definitions are part of react-bootstrap?
here's the codesandbox with the issue: https://codesandbox.io/s/react-bootstrap-formcontrol-bug-p2u2q

craigpg added a commit to craigpg/react-bootstrap that referenced this issue Sep 9, 2019
craigpg added a commit to craigpg/react-bootstrap that referenced this issue Sep 9, 2019
mlogan pushed a commit to mlogan/react-bootstrap that referenced this issue Sep 12, 2019
@EvgenyGulyaev
Copy link

EvgenyGulyaev commented Sep 25, 2019

Try it

queryChange(event:  React.ChangeEvent<HTMLInputElement>) {
   .....blah-blah
  }
onChange={(e: React.ChangeEvent<HTMLInputElement>) => queryChange(e)}

@Irfanhaidar-Mukhi
Copy link

Irfanhaidar-Mukhi commented Apr 17, 2024

When using React Bootstrap's time picker, I've noticed that in Chrome, a clock icon pops open next to the input box, allowing for time selection. However, in Firefox, this functionality seems to be missing. Why does this inconsistency occur between browsers?

         <Form.Control
              type='time'
              placeholder='Opening Time'
              name='Opening Time'
              autoComplete='off'
              onChange={handleOpeningTimeChange}
              value={openingTime}
              isValid={isValidTime}
              isInvalid={!isValidTime}
            />

Crome image
image

Firefox image
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants