Stefdelec Stefdelec - 11 days ago 9
TypeScript Question

How to reassign a list (in typescript) based on a "rank" object property?

I am trying to make a function to reassign a list based on their rank property.
For example:(my object has other property)

var array=[
{id:1,rank:2},
{id:18,rank:1},
{id:53,rank:3},
{id:3,rank:5},
{id:19,rank:4},//this item
]


This item {id:19,rank:4} is now in 2d position. The array becomes

item= { currentRank: 4; newRank: 2} //see below

array=[
{id:1,rank:3},
{id:18,rank:1},
{id:53,rank:4},
{id:3,rank:5},
{id:19,rank:2},
]


FYI : These items are re-order after a html drag&drop operation.
So I am trying to make a function to re-assign ranks based on the droped item rank.
I know the drop item new rank and its old rank.

So far I have done the following but it is not working for all cases:

public reorderArray(item: { currentRank: string; newRank: string }, array: { id: string, rank: string }[]): { id: string, rank: string } [] {


let arr = array.map(a => Object.assign({}, a)).sort((a, b) => (parseInt(a.rank) - parseInt(b.rank))).slice();
//To avoid to change the reference??
let isOrdered = arr.every((element, index, array) => {
return array[index + 1] ? element.rank + 1 == array[index + 1].rank : true
});

if (isOrdered && arr[0].rank == (1).toString()) {


if (parseInt(item.currentRank) < parseInt(item.newRank)) {
//on descend un élément dans la liste => +1 entre le currentRank et )le newRank
for (let i = parseInt(item.currentRank); i < parseInt(item.newRank); i++) {
arr[i].rank = (parseInt(arr[i].rank) - 1).toString();
}
arr[parseInt(item.currentRank)].rank = (parseInt(item.newRank)).toString();
}
else if (parseInt(item.currentRank) > parseInt(item.newRank)) {
for (let i = parseInt(item.newRank); i < parseInt(item.currentRank); i++) {
arr[i].rank = (parseInt(arr[i].rank) + 1).toString();
}
arr[parseInt(item.currentRank)].rank = (parseInt(item.newRank) + 1).toString();
}
return arr


}
else {
alert("This list is not ordered");
}
}


nb: if array is not properly oredered (rank is 1,3,4...), function doesn't do anything.

Answer

You could use an array for splicing and iterate then for the correction of the range.

function changeRank(object) {
    ranks.splice(object.newRank - 1, 0, ranks.splice(object.currentRank - 1, 1)[0]);
    ranks.forEach(function (a, i) {
        a.rank = i + 1;
    });
}

var array = [{ id: 1, rank: 2 }, { id: 18, rank: 1 }, { id: 53, rank: 3 }, { id: 3, rank: 5 }, { id: 19, rank: 4 }],
    ranks = [];

array.forEach(a => ranks[a.rank - 1] = a);

console.log(array);
changeRank({ currentRank: 4, newRank: 2 });
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }