React-beautiful-dnd: stop reordering

Created on 6 Mar 2018  路  28Comments  路  Source: atlassian/react-beautiful-dnd

Bug or feature request?

possibly a feature-request

I have 5 stages. I am moving cards from one stage to another by drag and drop. Cards in all the stages are sorted by last updated date. So, when I drag a card from one stage to another, the last updated date of card will be updated. So, my card should always be added to the top of the stage.

In this scenario, it looks foolish to reorder a card as it will be always added to the top. So, I want to stop the reordering of card even when animating it. So, when user drags a card he should see that it will be added to the top of the lane instead of any other order.

Most helpful comment

I did it ! 馃帀

1 - Disabled placeholder

_Exemple_

        <Droppable
          droppableId={`inventory-id-${idInventory}`}
          type="category-id-all"
        >
          {({ innerRef, placeholder, droppableProps }) => (
            <ItemsList ref={innerRef} {...droppableProps}>
              {itemsIds.map(renderItem)}
              <span
                style={{
                  display: "none"
                }}
              >
                {placeholder}
              </span>
            </ItemsList>
          )}
        </Droppable>

2 - Disabled animation translate except item isDragging.

function getStyle(style, snapshot) {
  if (!snapshot.isDragging) return {};
  if (!snapshot.isDropAnimating) {
    return style;
  }

  return {
    ...style,
    // cannot be 0, but make it super tiny
    transitionDuration: `0.001s`
  };
}


// [...]

<Draggable
    draggableId={`draggable-item-id${idItem}-inventory-id${idInventory}`}
    key={`draggable-${idItem}-${idInventory}`}
    index={index}
  >
    {({ innerRef, draggableProps, dragHandleProps }, snapshot) => (
      <div
        ref={innerRef}
        {...dragHandleProps}
        {...draggableProps}
        style={getStyle(draggableProps.style, snapshot)}
      >
                // [...]
      </div>
)}
</Draggable>

Exemple

exemple

All 28 comments

When you move into the new list items will naturally move out of the way. This will be the wrong interaction if you can only drop on the top of the list. You could probably use some smoke and mirrors to achieve what you are after but my head is not up to it atm.

The big idea would be that you would need to tell everything except the item dragging that it needs to be ignored by the system...

I'll think about this one later!

However the big thing to note is that your specific pattern is not currently supported

We also have a use case very similar to this. Would be a nice thing to see sometime in the future!

I also need to disable sort.

I have a similar issue with nested draggables. My app consists of manually sortable groups that themselves are droppables with draggables that are sorted automatically. Ideally I would like to disable the interactive reordering when dragging those inner draggables.

did anyone find a clever way to achieve this? @Vishal1419

Bumping this. Could be really useful with some patterns.

I'm looking for a feature like this as well. We're building something similar to JIRA, and we want the rule that if status is changing (i.e. moving to another list), then priority isn't changing (i.e. the global ordering of the cards don't change). In JIRA, you see an overlay appear over the list, and upon dropping it, it appears in the location that matches its global order. This conceptually sounds the same as the OP's request.

any solution yet for preventing from reorder while dragging ?????????

Any ideas?

We have a similar situation here. We need to drag cards among different lists. Depending on different scenarios, some can drop the card into the list and reorder it among other cards in the same list, some can only drop the card into the list but reordering is forbidden due to specific logic.

It would be much better if react-beautiful-dnd provides a more flexible interface to accommodate various situation.

There's a big assumption here that interaction should be the ultimate result, but interaction often plays along with different business logic which we're quite constrained by it.

I'm also bumping this. Maybe we can add a prop that visually acts like isDroppable but it allows you to still drop?

I tried a hack with using onDragUpdate to set isDroppable to true whenever the target index > 1 but it caused an infinite loop and crashed the app.

@alexreardon

I have achived this when you are dragging from a different droppable, but couldn't achive on the same droppable itself, yet. it was extremely complicated and hard to hack it, but in the end it works.

my use case was, there is a horizontal list/droppable on the left, and so many vertical droppables on the right hand side.
what I wanted to do was preventing reordering of the droppable's at the right side.

so, here goes how I achived the hack:
1: the lists on the right side are actually horizontal lists, even though they don't look like it
2: the draggables have position absolute
3: I calculate the width of the elements per vertical list on the right side, and give them a right value and width value, depending on how many elements there are (this has to be very precise if you want a good UI)
example from the right side (vertical lists):
right: !snapshot.isDragging &&${task.right}%`
what this does is, if the element is not dragging, it prevents them from reordering. normally they should reorder horizontally (since they are horizontal lists) but I hacked it with CSS. this part behaves perfect.

issues (which are similar to what people had so far):
1: if the element you are dragging is lets say 800px wide, and the list on the left is 300px wide, it does not calculate it correctly
2: I want 0 reordering of the list on the left side. I can do the same hack with position calculation, but I don't really believe its a very good solution (I will do this if I can't solve it)
3: since I calculate position of everything, it has to check what is going on each time, which WILL cause performance issues if you don't control what gets updated carefully (I already took care of this)
4: if your draggables don't have the same height, you have to calculate the position of each element (this is the case for my left side droppable, as the right side does similar to 100%/itemCount)

hopefully, somebody can find a better solution or the package gets an update. overall, very good package

I think the main thing everyone is looking for is the ability to move an item to another list, and not have that list shuffle around as you will be sorting it automatically. When the items shuffle, it gives the illusion that the user has control over the sort order and when they drop the item, the list reorders making it look funky.

My solution which works is to create a white box with position absolute covering the lists when the user starts the drag. The box just says "Drop here to x". This way the items below the cover may shuffle but the user at least doesn't see it. Simple but it works. Hope this helps someone.

Possible workaround: set in css transform: none!important; on all items except the one the is being dragged

Possible workaround: set in css transform: none!important; on all items except the one the is being dragged

I implemented this solution and it works, though it's not ideal. I'd love to just see a prop or something that would let us turn this behavior off.

Our solution:

export const maybeLockTransform = (
  isDragging: boolean,
  style: DraggingStyle | NotDraggingStyle
): DraggingStyle | NotDraggingStyle => {
  const transform = isDragging ? style.transform : "none !important";
  return { ...style, transform };
};

On further testing, my above solution breaks down if the user drags an item from List A, but then drops it back on List A. The item being dragged ends up being dropped on top of the nearest element in List A, and I can't seem to find a way to reset the transform after that 馃槩

Made a fix using isDropDisabled for 2 elements in 1 list.

I've managed to stop reordering by hiding placeholder:

<div style={{ visibility: 'hidden', height: 0 }}>
  {provided.placeholder}
</div>

I've managed to stop reordering by hiding placeholder:

<div style={{ visibility: 'hidden', height: 0 }}>
  {provided.placeholder}
</div>

not working for me...

This will do it, but is pretty hacky and performance could be a lot better if the DOM didn't have to update so much anyway: (props @yr-primexm)

.draggablecontainerhere > div {
  transform: none !important;
}

Would love to see a new prop for this instead. We're also creating a business-oriented workflow and columns are sorted statically.

I'm looking for this too - trying to swap two items between two lists and within a list. The animation that reorders doesn't make sense for that use case.

Same situation, I actually just want to be able to swap items in a list. And not reordering.

I ended up with a future-proof work-around while there isn't something official from the libraries creator: https://codesandbox.io/s/vertical-list-with-multiple-drop-targets-sr0wl

Basically I create an empty fake Droppable on top of the real Droppable that's only visible when it's being dragged over. When someone drops a Draggable on top of it, I just assume it was dropped on the real one. By doing that, we don't rely on changing the library internals.

PS: The code above could be simplified a lot, I just took one of the examples and tested this idea.

It's a bummer that react-beautiful-dnd is a not a general dnd solution. It should be clearly noted that this is a LIST DND+SORTING library. Basic behavior (no sorting) is missing here.

We also have a basic dnd requirement where an online quiz consists of labels that the user has to drag to one of a few buckets. The order of labels when dragged is irrelevant. Having the sorting behavior in this case will only confuse the user.

Once 12.0 is out we can look at this one.

Related:

  • #1390
  • #216

I did it ! 馃帀

1 - Disabled placeholder

_Exemple_

        <Droppable
          droppableId={`inventory-id-${idInventory}`}
          type="category-id-all"
        >
          {({ innerRef, placeholder, droppableProps }) => (
            <ItemsList ref={innerRef} {...droppableProps}>
              {itemsIds.map(renderItem)}
              <span
                style={{
                  display: "none"
                }}
              >
                {placeholder}
              </span>
            </ItemsList>
          )}
        </Droppable>

2 - Disabled animation translate except item isDragging.

function getStyle(style, snapshot) {
  if (!snapshot.isDragging) return {};
  if (!snapshot.isDropAnimating) {
    return style;
  }

  return {
    ...style,
    // cannot be 0, but make it super tiny
    transitionDuration: `0.001s`
  };
}


// [...]

<Draggable
    draggableId={`draggable-item-id${idItem}-inventory-id${idInventory}`}
    key={`draggable-${idItem}-${idInventory}`}
    index={index}
  >
    {({ innerRef, draggableProps, dragHandleProps }, snapshot) => (
      <div
        ref={innerRef}
        {...dragHandleProps}
        {...draggableProps}
        style={getStyle(draggableProps.style, snapshot)}
      >
                // [...]
      </div>
)}
</Draggable>

Exemple

exemple

@alexreardon any updates on whether or not a prop to disable animations might be added?

@Burdigalax hugely helpful. Saved hours. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

heymartinadams picture heymartinadams  路  3Comments

ibash picture ibash  路  3Comments

gitleet picture gitleet  路  3Comments

OmriAharon picture OmriAharon  路  3Comments

WJKwok picture WJKwok  路  3Comments