listeners from dnd-kit are interfering with the input:checkbox's onChange event

752 Views Asked by At

listeners from dnd-kit are interfering with the input:checkbox's onChange event

When I work with input:checkbox onchange event dnd-kit's {...listeners} interfere with the onchange event. Listeners disables onchange event in the input (I checked for input:checkbox and input:radio) element. If I remove/disable/commnet-out the {...listeners} input:checkbox event works just fine. But I need both {...listeners} and onchange event as without {...listeners} I cannot implement drag and drop.

The code where I tried is given below:

<div
            {...attributes}
            {...listeners}
            ref={setNodeRef}
            style={style}
            className={styles.itemWrapper}
        >
            <div
                className={styles.item}>
                <img src={item.image} alt="Image title goes here..." />
                <input type="checkbox" id={item.id.toString()}
                    onChange={() => {
                        console.log('checked/unchecked') // doesn't print in console
                        handleSelection(item.id)
                    }}
                />
                <label htmlFor={item.id.toString()} ></label>
            </div>
        </div>

** If I disable {...listeners} onchange event works fine **

<div
            {...attributes}
           // {...listeners} // disabled
            ref={setNodeRef}
            style={style}
            className={styles.itemWrapper}
        >
            <div
                className={styles.item}>
                <img src={item.image} alt="Image title goes here..." />
                <input type="checkbox" id={item.id.toString()}
                    onChange={() => {
                        console.log('checked/unchecked') // print in console 
                        handleSelection(item.id)
                    }}
                />
                <label htmlFor={item.id.toString()} ></label>
            </div>
        </div>
<div
            {...attributes}
            {...listeners}
            ref={setNodeRef}
            style={style}
            className={styles.itemWrapper}
        >
            <div
                className={styles.item}>
                <img src={item.image} alt="Image title goes here..." />
                <input type="checkbox" id={item.id.toString()}
                    onChange={() => {
                        console.log('checked/unchecked') // on change event should work with {...listenters enabled}
                        handleSelection(item.id)
                    }}
                />
                <label htmlFor={item.id.toString()} ></label>
            </div>
        </div>
3

There are 3 best solutions below

0
On

Maybe you should try to prevent the mouse event from bubbling up in the input event handler,I have encountered similar problems,hope it work for you too

like this :

const handleKeyDown =(e:any) => {
    if(e.key===' '){
        e.stopPropagation()
    }
}
0
On

You should try to put delay in useSensors, then it will not drag until user holds the element.

Check in documentation: Pointer Activation constraints or Touch Activation constraints.

const sensors = useSensors(
    useSensor(MouseSensor, {
      activationConstraint: {
        distance: 8,
      },
    }),
    useSensor(TouchSensor, {
      activationConstraint: {
        delay: 200,
        tolerance: 6,
      },
    }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    }),
  );
0
On

One option could be to use a drag handle, instead of the entire element being draggable. then the listeners won't conflict.

<div
    ref={setNodeRef}
    style={style}
    className={styles.itemWrapper}
>
    <div className={styles.item}>
        <div className="dragHandle" {...attributes} {...listeners}>drag handle</div>
        <img src={item.image} alt="Image title goes here..." />
        <input type="checkbox" id={item.id.toString()}
            onChange={() => {
            console.log('checked/unchecked') // on change event should work with {...listenters enabled}
            handleSelection(item.id)
            }}
        />
        <label htmlFor={item.id.toString()} ></label>
    </div>
</div>