skip to Main Content

I have a component that contains a Checkbox component from the @fluentui/react-components library, and I am using an onChange event on the Checkbox component.

const ContactText = ({ contact, contactKey, selectedContacts, setSelectedContacts }) => {

  return (
    <div>
      <img src={contactIcon} alt="Contact Icon" />
      <div>
        <Checkbox
          labelPosition="before"
          label={`${contact.firstname} ${contact.surname}`}
          checked={selectedContacts.filter((contact) => contact.key == contactKey).checked}
          //@ts-ignore - Ignore event parameter on onChange
          onChange={(event, data) => {
            setSelectedContacts((prevState: SelectedContactModel[]) =>
              data.checked
                ? [
                    ...prevState,
                    {
                      key: contactKey,
                      checked: data.checked,
                      companyKey: contact.companyKey,
                      companyName: contact.companyName,
                      individual: contact.individual,
                      title: contact.title,
                      firstname: contact.firstname,
                      surname: contact.surname,
                      telephone: contact.telephone,
                      mobile: contact.mobile,
                      retired: contact.retired,
                      address: contact.address,
                      postcode: contact.postcode,
                      email: contact.email,
                    },
                  ]
                : prevState.filter((contact) => contact.key !== contactKey)
            );
          }}
        />
        {contact.email != "" ? <SecondaryText text={contact.email} /> : <></>}
        {contact.telephone != "" ? <TertiaryText text={contact.telephone} /> : <></>}
        {contact.mobile != "" ? <TertiaryText text={contact.mobile} /> : <></>}
      </div>
    </div>
  );
};

I want to have the onChange to happen when I click the outermost div of the ContactText component. I have seen people using useRef although I am wondering if there are different ways of doing this.

2

Answers


  1. You can either add a onClick etc on the div element and do what you do inside the onChange in the Checkbox (although you will need to compute checked like you do in the render), or you can just change the <div> into a <label> as clicking on a label will delegate the click to whichever <input> element it wraps (or has a for with a matching ID).

     const ContactText = ({ contact, contactKey, selectedContacts, setSelectedContacts }) => {
      return (
        <label> {/* <------------ */}
          <img src={contactIcon} alt="Contact Icon" />
          <div>
            <Checkbox
              labelPosition="before"
              label={`${contact.firstname} ${contact.surname}`}
              checked={selectedContacts.filter((contact) => contact.key == contactKey).checked}
              //@ts-ignore - Ignore event parameter on onChange
              onChange={(event, data) => {
                setSelectedContacts((prevState: SelectedContactModel[]) =>
                  data.checked
                    ? [
                        ...prevState,
                        {
                          key: contactKey,
                          checked: data.checked,
                          companyKey: contact.companyKey,
                          companyName: contact.companyName,
                          individual: contact.individual,
                          title: contact.title,
                          firstname: contact.firstname,
                          surname: contact.surname,
                          telephone: contact.telephone,
                          mobile: contact.mobile,
                          retired: contact.retired,
                          address: contact.address,
                          postcode: contact.postcode,
                          email: contact.email,
                        },
                      ]
                    : prevState.filter((contact) => contact.key !== contactKey)
                );
              }}
            />
            {contact.email != "" ? <SecondaryText text={contact.email} /> : <></>}
            {contact.telephone != "" ? <TertiaryText text={contact.telephone} /> : <></>}
            {contact.mobile != "" ? <TertiaryText text={contact.mobile} /> : <></>}
          </div>
        </label>
      );
    };
    
    Login or Signup to reply.
  2. Try this

    const ContactText = React.forwardRef<{ onChange: (event: any, data: any) => void; scrollIntoViewOnClick: () => void }, HTMLDivElement>(({ contact, contactKey, selectedContacts, setSelectedContacts }, ref) => {
      React.useImperativeHandle((ref) => ({
        // You could name this whatever you want, we'll call it 'onChange'
        onChange: handleChange,
        // Just for the sake of this example and what 'useImperativeHandle' is used for
        scrollIntoViewOnClick: () => {
          // Logic to query for your div on the page and then scroll into view
          console.log('should scroll into view');
        }
      }));
    
      const handleChange = (event, data) => {
                setSelectedContacts((prevState: SelectedContactModel[]) =>
                  data.checked
                    ? [
                        ...prevState,
                        {
                          key: contactKey,
                          checked: data.checked,
                          companyKey: contact.companyKey,
                          companyName: contact.companyName,
                          individual: contact.individual,
                          title: contact.title,
                          firstname: contact.firstname,
                          surname: contact.surname,
                          telephone: contact.telephone,
                          mobile: contact.mobile,
                          retired: contact.retired,
                          address: contact.address,
                          postcode: contact.postcode,
                          email: contact.email,
                        },
                      ]
                    : prevState.filter((contact) => contact.key !== contactKey)
                );
              };
    
      return (
        <div ref={ref}>
          <img src={contactIcon} alt="Contact Icon" />
          <div>
            <Checkbox
              labelPosition="before"
              label={`${contact.firstname} ${contact.surname}`}
              checked={selectedContacts.filter((contact) => contact.key == contactKey).checked}
              //@ts-ignore - Ignore event parameter on onChange
              onChange={handleChange}
            />
            {contact.email != "" ? <SecondaryText text={contact.email} /> : <></>}
            {contact.telephone != "" ? <TertiaryText text={contact.telephone} /> : <></>}
            {contact.mobile != "" ? <TertiaryText text={contact.mobile} /> : <></>}
          </div>
        </div>
      );
    });
    

    useImperativeHandle enables you to expose methods that only you want to be available outside of your component.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search