reactjstypescriptreact-table

How to add radio buttons in cell within react table component?


i am new to programming with react and typescript and i am currently trying to add two radio buttons inside a react table row cell.

below is what i am aiming for.

enter image description here

as seen from above i want to add two radio buttons namely button1 and button2 to each row under radio buttons column. these radio buttons are shown only when user selects that row. by default button1 should be selected.

on selecting button2 we need to add the id of the selected row in an array. so for example if we select button2 of first row with id '1' then array should contain ['1']. then if user selects second row with id'2' then array should contain ['1','2']. now if user deselects button2 and selects button1 of second row with id '2' then array should contain ['1'].

i have tried below solution to do so,

CustomRadioButtonComponent.tsx

const CustomRadioButtonComponent: React.FC<SomeProps> = ({
    id,
    info,
    onBlur,
    onRadioButton1Change,
    onRadioButton2Change,
}) => {
    const handleRadioButton1Change: React.ChangeEventHandler<HTMLInputElement> =
        React.useCallback((event: any) => onRadioButton1Change(),
        [id, onRadioButton1Change]
    );

    const handleRadioButton2Change: React.ChangeEventHandler<HTMLInputElement> =
        React.useCallback((event: any) => {
            onRadioButton2Change(id, event.target.checked);
        }, [id, onRadioButton2Change]
    );
    return (
        <Flex flex={1}>
            <RadioButton
                name="radio"
                id="btn1"
                label="button1"
                onChange={handleRadioButton1Change}
                onBlur={onBlur}
                checked={info.length === 0}
         />
         <RadioButton
             name="radio"
             id="btn2"
             label="button2"
             checked={info.length > 0}
             onChange={handleRadioButton2Change}
             onBlur={onBlur}
         />
     </Flex>
 );

};

main.tsx

const mainStep: React.FC<MainStepProps> = props => {
    const info = values[INFO_KEY]; // form field value where we store the ids of 
    //selected rows

    
    const handleRadioButton1Change = React.useCallback(() => {
        setFieldValue(INFO_KEY, []); // WRONG LOGIC
    }, [setFieldValue]);

    const handleRadioButton2Change = React.useCallback(
        (id: any, state: any) => { // WRONG LOGIC
            const actualId = allInfoMap[id] ?? id;
            const infoAfterChange = state
                ? [...info, actualId]
                : info.filter(item => item !== actualId);
            setFieldValue(INFO_KEY, infoAfterChange);
     }, [info, setFieldValue, allInfoMap]
 );


    const columns: Column<Data>[] = [
        {
            Header: 'Name',
            id: 'name' ,
        } as ColumnWithId<Data>,x
        {
            Header: 'Radio buttons',
            id: 'radioButtons',
            accessor: ({ id, handleButton1Change, handleButton2Change, info, onBlur}) 
                => ({
                       id,
                       handleButton1Change,
                       handleButton2Change,
                       info,
                       onBlur,
                   }),
            Cell: ({
                      value: {
                          id,
                          handleButton1Change,
                          handleButton2Change,
                          info,
                          onBlur,
                      },
                      row: { selectState },
                  }) => {
                      if (selectState === 1) {
                          return (
                              <CustomRadioButtonComponent
                                  info = {info}
                                  onBlur={onBlur}
                                  id={id}
                                  onRadioButton1Change={handleRadioButton1Change}
                                  onRadioButton2Change={handleRadioButton2Change}
                               />
                           }
                       } as any,
                       {
                           Header: 'Version',
                           // version logic
                       },
                   ];
                 

    const tableData = React.useMemo(() =>
        data.map(item => {
            return {
                ...item,
                handleButton1Change(),
                handleButton2Change(),
                info,
            };
        }),[data, handleButton1Change, handleButton2Change, info];
    return (
        <Table<Data>
            data={tableData}
            columns={columns}
        />
    );
}

the problem with above code is that it doesnot select the right radiobuttons if i select button2 on row1 and then select button2 on row2 then the button2 on row 1 is deselected.

also the button1 is not selected on default.

could someone help me with this. thanks.


Solution

  • For the first problem, where selecting button2 in one row deselects button2 in another row, you need to give each radio input in each row the same name. This name should be different from the names of radio inputs in other rows.

    For example, the first row might be like this:

    <Row1>
      <RadioButton
        name="name1"
        {...otherProps}
      />
      <RadioButton
        name="name1"
        {...otherProps}
      />
    </Row1>
    

    The second row

    <Row2>
      <RadioButton
        name="name2"
        {...otherProps}
      />
      <RadioButton
        name="name2"
        {...otherProps}
      />
    </Row2>
    

    And so on...

    Additionally, to make the first radio button always checked during the first rendering, you can use the defaultChecked attribute:

    <RadioButton
      name="name1"
      defaultChecked
      {...otherProps}
    />