clauderic / react-sortable-hoc

A set of higher-order components to turn any list into an animated, accessible and touch-friendly sortable list✌️
https://clauderic.github.io/react-sortable-hoc/
MIT License
10.81k stars 979 forks source link

Pass parameters to onSortEnd function #494

Closed Adel-J closed 5 years ago

Adel-J commented 5 years ago

I'm trying to pass a parameters to onSortEnd function but always the data is empty for mine but the indexing work fine.

onSortEndCustom = ({oldIndex, newIndex}, data) => { console.log(data); }

I create my custom function it is working but seems call every time the list changes even if not change the sort, I want same concept as onSortEnd.

So any one know why it is not working to pass parameters or any best solutions?

clauderic commented 5 years ago

I'm not really sure I understand your question or the problem. Could you rephrase the question or share a CodeSandbox replicating the issue? Closing this until more info is provided

WikeC commented 5 years ago

I think I understand what he means because I meet the same case. Here is my case: I have a list group. How to change the order of the list inside the group?

Here is my example: groupItems: [ {title: "Title 1", listItems: ["item 1.1", "item 1.2", "item 1.3"]}, {title: "Title 2", listItems: ["item 2.1", "item 2.2", " item 2.3 "]} ]

If I want to change the order of the list in the second array, (groupItems [1] .listItems) I need to tell the onSortEnd the id of the array to modify (for example):

onSortEnd = {() => this.onChangeItem (idTable)}

And in the function:

onChangeItem = ({oldIndex, newIndex}, idTable) => { console.log (idTable) // undefined }

What would be the solution?

Thank you for your reply.

WikeC commented 5 years ago

I think I understand what he means because I meet the same case. Here is my case: I have a list group. How to change the order of the list inside the group?

Here is my example: groupItems: [ {title: "Title 1", listItems: ["item 1.1", "item 1.2", "item 1.3"]}, {title: "Title 2", listItems: ["item 2.1", "item 2.2", " item 2.3 "]} ]

If I want to change the order of the list in the second array, (groupItems [1] .listItems) I need to tell the onSortEnd the id of the array to modify (for example):

onSortEnd = {() => this.onChangeItem (idTable)}

And in the function:

onChangeItem = ({oldIndex, newIndex}, idTable) => { console.log (idTable) // undefined }

What would be the solution?

Thank you for your reply.

Ok got it ! Need to use the property collection.

OscarLeung19920222 commented 5 years ago

@WikeC Hi, I have found this issue and it seem likes you have got the idea of how to solve it. I am currently encountering same problem with the onSortEnd function. Would you advise a bit more details on the solution? Really appreciated your help.

WikeC commented 5 years ago

@OscarLeung19920222 , Hi. In your loop, you must assign your id to collection.

For example (if we take the basic example from the doc: https://github.com/clauderic/react-sortable-hoc),

{items.map((value, index) => ( <SortableItem key={item-${index}} index={index} value={value} collection={myId} /> ))}

And in your function,

onSortEnd = ({oldIndex, newIndex, collection}) => { console.log(collection) // myId }

Hope I helped you.

XeniaSiskaki commented 5 years ago

I don't think the collection parameter is used for the use case that @Adel-J mentioned in his first comment. From the docs:

The collection the element is part of. This is useful if you have multiple groups of sortable elements within the same SortableContainer

which if I understand correctly means that the value will just be an identifier for the group and not some custom data.

@clauderic I'm facing the same problem. I want to pass some custom data and read them in the onSortEnd. Is that currently possible? To be more specific, each SortableElement in my SortableContainer has an ID which I need to know when handling the sort end.

sagar-gavhane commented 4 years ago

Yes. You can pass a parameter to onSortEnd method using collection but it's only accepting number and string.

<SortableList
  ...props
  collection={myId}
/>
handleSortEvent = ({ oldIndex, newIndex, collection }, e) => {
   // here, collection=myId
  ...code
}
sercanov commented 4 years ago

@XeniaSiskaki is right, when you pass collection attribute to SortableItem, sorting brokes. I also need to get item ID ( or any other data ) in onSortEnd function. The only way seems to work is adding custom attribute to SortableItem, and try to parse it in onSortEnd's nodes property. Like this;

  1. Add custom field to SortableItem

    const SortableList = SortableContainer(
    ({ ids = [], data = [], onClick, onEdit, selected, ...props }) => {
    if (data)
      return (
        <List component="nav">
          {ids.map((id, index) => (
            <SortableItem
              key={id}
              index={index}
              // collection={id} this brokes sorting 
              itemID={id} // Add custom field to pass data
              value={data[id]}
            />
          ))}
        </List>
      );
    }
    );
  2. Parse itemID in onSortEnd

    const onSortEnd = ({ oldIndex, newIndex, collection, nodes, ...rest }) => {
      console.log(nodes[oldIndex].node.attributes.itemid.value);
    };
image

Conclusion; All this should be less painful

PCPbiscuit commented 3 years ago

Found a much better solution to this. I needed the id of an item so I was also trying to pass it using 'collection' prop however it does indeed break the whole dnd. My solution to this is to use oldIndex to access the current item in the state:

onSortEnd ({oldIndex, newIndex}) { let id = this.state.items[oldIndex].id }

Anisha95 commented 2 years ago

As per my observation, if we pass params to the onSortEnd like this

<SortableList
  ...props
  onSortEnd={(e) => onSortEnd({e: e, myId: myId}}
/>

Then on the function, the prop field myId could be received :


onSortEnd = ({e, myId}, data) => {
     let myId = myId;  // props => {e: {collection: 0, newIndex: [newIndex], oldIndex: [oldIndex], isKeySorting: undefined, 
                                           //nodes: 
                                           // Array(2)}
                                          // myId: myId}
}
chengwang1009 commented 7 months ago

I don't know am I too late for this.

But here is the solution to pass data as props

`const onSortEndHandler = ({oldIndex, newIndex, ...props}) => {

  const questionsArray = props.questionsArray;
  const setQuestionsArray = props.setQuestionsArray;

  const arr = arrayMoveImmutable(questionsArray, oldIndex, newIndex);
  setQuestionsArray(arr);
};

<SortableList 
        items={questionsArray}
    onSortEnd={({oldIndex, newIndex})=>{onSortEndHandler({oldIndex, newIndex, questionsArray, setQuestionsArray})}}
        axis="xy"
 />`