webrobert's avatar

prevent default on drag/sorting

Desired result

I want the item to be clickable link. BUT also IF the user moves the item by dragging it to disable the click. Im not sure how to access the javascript event.

The sorting works... but adding the link to the element it sends the page as soon as the dragging stops/drops

Setup

I am using Livewire Sortable.js, its a wrapper for SortableJS so apparently all the options [the functions too?] are available somehow? I did add... forceFallback which prevent html5 from hijacking my styling.

I also saw this post where someone just wired up sortablejs directly to use Livewire. If I rewrote the logic to use sortablejs directly, idk.

How can I prevent the default click action when moving and allow it to click otherwise?

Here is the code

nothing special... I tried adding preventOnFilter to the options...

 <div 
  wire:sortable="updateToolOrder"
  wire:sortable.options="{ forceFallback: true, preventOnFilter: true }">
  @foreach($project->activeTools as $tool)
      <x-dynamic-component :$tool :component="'project.tool.card-'. $tool->modelName()" />
  @endforeach
</div>

and a basic render of the dynamic component...

<div class"relative ..." wire:sortable.item="12" wire:key="tool-12">
    <h3>Card title</h3>
    <div class="flex overflow-hidden">
		// just some card content
    </div>
    <a href="a url here" class="absolute inset-0"></a>
</div>
0 likes
7 replies
vincent15000's avatar

I just reformulate your problem to be sure to understand.

You can either click or drag and drop an element (the same element).

To drag an element, you have to mouse down and mouse up, and for the moment the drag and drop works but also generates a click (mouse down + mouse up).

Is it the problem ?

1 like
webrobert's avatar

So the drag and drop work. But as soon as you let go it it registers the click and goes the link.

I want it to drag and drop OR click not both

1 like
vincent15000's avatar

@webrobert Ok so the drag and drop also clicks on the link. I'll have a look, I already used Livewire sortable.

webrobert's avatar

@vincent15000 correct. I didn’t find a solution so I just added a handle to move the item as a temp solution. Ideally the element is smart enough to know the difference between a click and a drag. It’s some kind of time out I just don’t know how to add it.

1 like
vincent15000's avatar

@webrobert I had applied the same solution as yours : I added a handle. But I'm interested in knowing how click and drag and drop at the same place.

bmooreitul's avatar

I know this is an old question, but it's one I've run into many times... Thought I might throw out how I've fixed it in the past. Maybe itll help someone else

<div x-data="{
    clickTok 	: false,
    clickTimer 	: null,
    clickDown() {
        this.clickTok = false;

        //WAIT FOR HALF A SECOND (OR WHATEVER INTERVAL YOU WANT)
        this.clickTimer = setTimeout(() => { this.clickTok = true; }, 500); 
    },

    //RUN CHECK IF clickTok IS STILL RUNNING
    clickUp(e) {

    	//STOP TRACKING TIME MOUSE WAS CLICKED
        clearTimeout(this.clickTimer);

        //IS clickTok STILL RUNNING?
        if(this.clickTok){

        	//STOP OTHER EVENTS FROM FIRING
            e.stopImmediatePropagation(); // <----- THIS IS WHAT YOU WANT

            //FLAG USER CLICK STATUS
            this.clickTok = false;           
        }
    }
}" @mousedown="clickDown()" @mouseup="clickUp($e)" >Ignore my mouse actions after 500ms</div>

Please or to participate in this conversation.