Dnd-kit sortable list with drag handle - setActivatorNodeRef has no effect

5k Views Asked by At

I have an issue with dnd-kit library. I'm trying to achieve sortable list with drag handle activator. The issue is I cannot set drag handle (button) to be only drag activator. Instead, the entire parent element stays active.

SortableItem component:


    const SortableItem: FunctionComponent<{ id: string }> = (props) => {
      const {
        attributes,
        listeners,
        setNodeRef,
        setActivatorNodeRef,
        transform,
        transition,
      } = useSortable({ id: props.id });


      const context: Context = {
        attributes: attributes,
        listeners: listeners,
        setActivatorNodeRef: setActivatorNodeRef
      }


      return (
        <SortableItemContext.Provider value={context}>
          <div ref={setNodeRef} {...attributes} {...listeners}>
            {props.children}
          </div>
        </SortableItemContext.Provider>
      );
    }

DragHandle component:


    export const DragHandle: FunctionComponent = () => {

      const { attributes, listeners, setActivatorNodeRef } = useContext(SortableItemContext);
      return <button type="button"
                     className="DragHandle"
                     {...attributes} {...listeners}
                     ref={setActivatorNodeRef}>
        <svg viewBox="0 0 20 20" width="12">
          <path d="cleaned..."></path>
        </svg>
      </button>
    }


SortableList (wrapper):

    <DndContext collisionDetection={closestCenter}
                modifiers={[restrictToVerticalAxis, restrictToWindowEdges]}
                onDragEnd={onSortEnd}>

      <SortableContext items={ids}
        strategy={verticalListSortingStrategy}>

        { props.data.map((item, itemKey) => (
          <SortableItem id={item[props.idKeyName]}
                        key={`si-${item[props.idKeyName]}`}>
            { props.mapFunction(item, itemKey) }
          </SortableItem>
        ))}
  
      </SortableContext>

    </DndContext>

Usage:

<SortableList onSortEnd={onSortEnd}
            idKeyName={'id'}
            data={data}
            mapFunction={(item: ICreateQuestionAnswer, itemKey: number) => <div>
                <DragHandle />
                -----
              </div>
            } />

I followed docs about setActivatorNodeRef but it seams to have no effect, no warnings or errors either, doc link

1

There are 1 best solutions below

0
On

There is info about it in doc under 'Listeners':

setNodeRef should be in parent (whole element which will be draggable), but attributes and listeners should be only in button props.

import {useDraggable} from '@dnd-kit/core';


function Draggable() {
  const {attributes, listeners, setNodeRef} = useDraggable({
    id: 'unique-id',
  });
  
  return (
    <div ref={setNodeRef}>

      /* Some other content that does not activate dragging */

      <button {...listeners} {...attributes}>Drag handle</button>
    </div>
  );
}

https://docs.dndkit.com/api-documentation/draggable/usedraggable