Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate/trigger an React.ChangeEvent<HTMLInputElement> with empty value on input

I'm building a custom React Input (using Chakra-UI) who can be cleaned using an Icon button (when you click on the Button, the value is updated to "").

The issue is, I have to propagate an React.ChangeEvent<HTMLInputElement> event for onChange function (to be able to be used as any ChakraUI Input).

Frist Try: Build a new Event from nothing.

For now this is my Component, but I have no idea how to generate a new onChange event on the button onClick event.

import React, { useState } from "react"
import { IconButton, InputGroup, InputGroupProps, InputProps, InputRightElement, Input } from "@chakra-ui/react"
import { MdClose } from "react-icons/md";

export type CleanableInputProps = InputProps & { 
  Input?: (props: InputProps) => JSX.Element,
  inputGroupProps?: InputGroupProps,
}

export const CleanableInput = ({
  inputGroupProps = {}, // Allow to inject props on wrapper
  ...props
}: CleanableInputProps): JSX.Element => {

  const [search, setSearch] = useState<CleanableInputProps['value']>(props?.value);
  const _setSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearch(e.currentTarget.value); // Update React value
    props.onChange?.(e);
  }

  return (
    <InputGroup {...inputGroupProps}>
      <Input {...props} value={search} onChange={_setSearch} />
      <InputRightElement>
        <IconButton  icon={<MdClose />} aria-label="clean" onClick={() => {

          //
          // Create event Input onChange event with value=""
          // e = __________________;
          //

          _setSearch(e);

        }}/>
      </InputRightElement>
    </InputGroup>
  )
}

Second try: Update by ref the input and trigger input onChange

I did another version using input ref, and updating the input value then trigger the event but:

  • Now I have issue using another component then ChakraUI input
  • The input value is well updated (visually it's blank after clicking) but the onChange is never triggered.
import React, { useRef } from "react"
import { IconButton, InputGroup, InputGroupProps, InputProps, InputRightElement, Input } from "@chakra-ui/react"
import { MdClose } from "react-icons/md";

export type CleanableInputProps = InputProps & {
  inputGroupProps?: InputGroupProps,
}

export const CleanableInput = ({
  inputGroupProps = {}, // Allow to inject props on wrapper
  ...props
}: CleanableInputProps): JSX.Element => {

  const inputRef = useRef<HTMLInputElement | null>(null);

  return (
    <InputGroup {...inputGroupProps}>
      <Input {...props} ref={inputRef} value={props.value} />
      <InputRightElement>
        <IconButton icon={<MdClose />} aria-label="" onClick={() => {
          if (inputRef != undefined && inputRef.current != undefined) {
            // Update value (working)
            inputRef.current.value = "";

            // Trigger onChange event manually (Not working)
            let event = new Event('input', { bubbles: true });
            inputRef.current.dispatchEvent(event);
          }
        }} />
      </InputRightElement>
    </InputGroup>
  )
}
like image 881
Arthur Avatar asked Dec 17 '25 12:12

Arthur


1 Answers

After days of looking for answer, look like the way I updated the value into the referred input wasn't good, so the event was well trigger but didn't see any update (so was not propagated)

This is working good:

  // Update the value by ref
  var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")!.set;
  nativeInputValueSetter!.call(inputRef.current, '');

  // Then trigger the onChange event of the input 
  //    for some input (select, textarea) we may want to trigger 'change' instead of 'input' who not listen to input event
  inputRef.current.dispatchEvent(new Event('input', { bubbles: true }));

Complete solution:

import React, { useRef } from "react"
import { IconButton, InputGroup, InputGroupProps, InputProps, InputRightElement, Input } from "@chakra-ui/react"
import { MdClose } from "react-icons/md";

export type CleanableInputProps = InputProps & {
  inputGroupProps?: InputGroupProps,
  triggerEventName?: 'input' | 'change',
}

export const CleanableInput = ({
  inputGroupProps = {}, // Allow to inject props on wrapper
  triggerEventName = 'input',
  ...props
}: CleanableInputProps): JSX.Element => {

  const inputRef = useRef<HTMLInputElement | null>(null);

  return (
    <InputGroup {...inputGroupProps}>
      <Input {...props} ref={inputRef} value={props.value} />
      <InputRightElement>
        <IconButton icon={<MdClose />} aria-label="" onClick={() => {
          if (inputRef != undefined && inputRef.current != undefined) {
            // Update the value by ref
            var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")!.set;
            nativeInputValueSetter!.call(inputRef.current, '');

            // Then trigger the onChange event of the input 
            //    for some input (select, textarea) we may want to trigger 'change' instead of 'input' who not listen to input event
            inputRef.current.dispatchEvent(new Event(triggerEventName, { bubbles: true }));
          }
        }} />
      </InputRightElement>
    </InputGroup>
  )
}
like image 74
Arthur Avatar answered Dec 19 '25 00:12

Arthur



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!