How to use Nested Sort
The initial idea of Nested Sort came from the idea of having a JS class to receive a collection (array) of database records sorted on a specific order (the value of a specific column is the id of another column) and provide a way for changing the order of them via the HTML drag and drop (dnd) functionality.
So let's assume we have an array of "items":
[
{ id: 1, text: "Item 1" },
{ id: 11, text: "Item 1-1", parent: 1 },
{ id: 2, text: "Item 2" },
{ id: 3, text: "Item 3" },
{ id: 111, text: "Item 1-1-1", parent: 11 },
{ id: 112, text: "Item 1-1-2", parent: 11 },
{ id: 31, text: "Item 3-1", parent: 3 }
]
First put the following HTML element on your document where you want the list to be shown:
<div id="nested-sort-wrap"></div>
Now the following JS code would convert the array of items into a nested list and place it inside the HTML element you created earlier.
new NestedSort({
data: [
{ id: 1, text: "Item 1" },
{ id: 11, text: "Item 1-1", parent: 1 },
{ id: 2, text: "Item 2" },
{ id: 3, text: "Item 3" },
{ id: 111, text: "Item 1-1-1", parent: 11 },
{ id: 112, text: "Item 1-1-2", parent: 11 },
{ id: 31, text: "Item 3-1", parent: 3 }
],
actions: {
onDrop(data) { // receives the new list structure JSON after dropping an item
console.log(data)
}
},
el: '#nested-sort-wrap', // a wrapper for the dynamically generated list element
listClassNames: ['nested-sort'], // an array of custom class names for the dynamically generated list element
renderListItem: (el, { id }) => {
if (id === 2) el.textContent += ' (this is a custom rendered item)'
return el
}
})
Data mapping
The following table shows a map of different properties on every data item:
Name | Role | Required |
---|---|---|
id | This is the unique identifier of the item | Yes |
text | This appears as the list item text | Yes |
parent | This is the id of the parent item | No |
But what if your items have different property names? As an example, let's say your data is structured as:
[
{ _id: 1, title: "Item 1" },
{ _id: 11, title: "Item 1-1", parent_id: 1 },
{ _id: 2, title: "Item 2" },
{ _id: 3, title: "Item 3" },
{ _id: 111, title: "Item 1-1-1", parent_id: 11 },
{ _id: 112, title: "Item 1-1-2", parent_id: 11 },
{ _id: 31, title: "Item 3-1", parent_id: 3 }
]
In this case, you can let Nested Sort know about this specific structure
by using the propertyMap
property of the object you're
passing to the constructor (called Config object from
now on):
new NestedSort({
data: [
{ _id: 1, title: 'Item 1' },
{ _id: 11, title: 'Item 1-1', parent_id: 1 },
{ _id: 2, title: 'Item 2' },
{ _id: 3, title: 'Item 3' },
{ _id: 111, title: 'Item 1-1-1', parent_id: 11 },
{ _id: 112, title: 'Item 1-1-2', parent_id: 11 },
{ _id: 31, title: 'Item 3-1', parent_id: 3 }
],
propertyMap: {
id: '_id',
parent: 'parent_id',
text: 'title',
},
el: '#nested-sort-wrap',
listClassNames: ['nested-sort']
})
Custom render of list items (v5.1.0)
The default list item element rendered by the library might not be ideal
for every use case. Therefore, a hook has been introduced to give us
more control over the list items html content. The
renderListItem
option is supposed to be a function which
receives the following 2 arguments and returns a list item element:
el
: the default list item element created by the libraryitem
: the representative data item
new NestedSort({
data: [
{ id: 1, text: "Item 1" },
],
renderListItem: (el, { id }) => {
if (id === 1) el.textContent += ' (this is a custom rendered item)'
return el
},
...otherOptions
})