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

4

5

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>
Analog answered 3/11, 2023 at 9:16 Comment(0)
D
7

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,
    }),
  );
Demurral answered 29/11, 2023 at 13:33 Comment(1)
This was the answer for me. Had a 'close' icon on the top of a nested component and used 'sensors' to enable the onClick functionality.Conrad
J
2

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>
Jebel answered 20/12, 2023 at 15:49 Comment(0)
K
1

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()
    }
}
Kunlun answered 22/11, 2023 at 11:3 Comment(0)
U
0
onPointerDown={(e) => e.stopPropagation()} // Detiene la propagación del evento

is this the event PointerDown but you need to put this in checkbox

Like this

 <input
      type="checkbox"
      checked={item.active}
      onPointerDown={(e) => e.stopPropagation()} // Detiene la propagación del evento
      onChange={() => handleCheckboxChange(item.id.toString())}
       className="form-checkbox h-5 w-5 text-blue-600"
  />
Unusual answered 19/10 at 17:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.