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

779 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
ever nothing 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
Werthis 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
Skäggiga Mannen 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>