3

I have a table where I would like to change the order or rows by moving an item Up or Down. The element select here(T17180054) with index 3 should move up and have a new index of 2 and keep the selection preferably.

enter image description here

This is my HTML:

<table st-safe-src="flow3.dataSet" st-table="flow3.displayed" class="table table-striped">
    <thead>
        <tr>
            <th st-sort="method">Method</th>
            <th st-sort="sample">Sample</th>
            <th st-sort="parameters">Parameters</th>
        </tr>
    </thead>
    <tbody ui-sortable ng-model="flow3.displayed">
        <tr ng-repeat="row in flow3.displayed track by $index" style="cursor: move;" 
            ng-click="row.selected = !row.selected; flow3.selectRow($event, row, index)" 
            ng-class="{success: row.selected}">>
            <td>{{row.method.name}}</td>
            <td>{{row.sample}}</td>
            <td>
                <span ng-repeat="parameter in row.parameters">   
                    {{parameter.methodInputParameter.name}} : {{parameter.value}}<br/></span>
            </td>
            <td>
                <button type="button" ng-click="flow3.removeItem(row)"
                    class="btn btn-danger btn-sm btn-round pull-right"
                    ng-disabled="flow3.confirmDisabled">
                        <i class="glyphicon glyphicon-trash"></i>
                </button>
            </td>
        </tr>
    </tbody>
</table>

This is my two Up and Down buttons

<div class="row">
    <div class="col-xs-6">
        <div class="btn btn-info btn-lg btn-full-width">
            <span class="glyphicon glyphicon-menu-up" ng-click="flow3.moveItemUp();"></span> Up
        </div>
    </div>
    <div class="col-xs-6">
        <div class="btn btn-info btn-lg btn-full-width">
            <span class="glyphicon glyphicon-menu-down" ng-click="flow3.moveItemDown();"></span> Down
        </div>
    </div>
</div>

This is my JS : I have tried to use the splice method by I had wrong results each time. Is there a better alternative?

flow3.moveItemDown = function moveItemDown() {
    var index = flow3.dataSet.indexOf(flow3.selectedItem);

    if(index == 0) {
        return;
    } else {
        flow3.dataSet.splice(?, ?, ? , ?)
    }
}
Nikolaj Dam Larsen
  • 5,455
  • 4
  • 32
  • 45
ErEcTuS
  • 777
  • 1
  • 14
  • 33

3 Answers3

3

You can use splice, but you would need to use it twice: once to remove the item from the old position, and once to re-add the item to the new position:

flow3.moveItemDown = function moveItemDown() {
    var index = flow3.dataSet.indexOf(flow3.selectedItem);

    if(index <= 0) {
        // The item cannot be moved up if it's already the first in the array;
        // and account for -1, index not found
        return;
    } else {
        // Remove value to replace
        var removed = flow3.dataSet.splice(index, 1);
        // Re-add removed value to the previous index
        flow3.dataSet.splice(index - 1, 0, removed[0]);
    }
}

If you try to do both using the same splice the added items will be added at the start index of the splice, resulting in the item being re-added at its original index.

more about array.splice

Also, dont forget to account for the array length when moving items down, you cannot move the last item down anymore ;)

ScintillatingSpider
  • 338
  • 1
  • 9
  • 14
  • 1
    Hey ScintillatingSpider..It works, thanks a lot. Great elegant solution ;-) Indeed, about the array length – ErEcTuS Jul 04 '17 at 12:38
  • The code above is actually for moving the item UP, not down. – Sagi Oct 24 '20 at 10:41
  • @Sagi How do you mean? if you would run the function with dataSet set to `['item 1', 'item 2', 'item 3']` and selectedItem to `'item 2'`, it would result in the following dataSet: `["item 2", "item 1", "item 3"]`. `item 2` has been moved down from index `1` to index `0` – ScintillatingSpider Oct 24 '20 at 11:08
  • Ok its the same thing. Down on the index, and up on the list. Anyhow this answer works for me. Thanks. – Sagi Oct 24 '20 at 19:33
1

You can try this also. Its working fine for me.

// Move list items up or down or swap
    $scope.moveItem = function (origin, destination) {
        var temp = $scope.list[destination];
        $scope.list[destination] = $scope.list[origin];
        $scope.list[origin] = temp;
    };

    // Move list item Up
    $scope.listItemUp = function (itemIndex) {
        $scope.moveItem(itemIndex, itemIndex - 1);
    };

    // Move list item Down
    $scope.listItemDown = function (itemIndex) {
        $scope.moveItem(itemIndex, itemIndex + 1);
    };
Ravindra Kumar
  • 1,842
  • 14
  • 23
  • thanks Ravindra..I've tried it too. It works but I'll stick to the solution below with splice() – ErEcTuS Jul 04 '17 at 12:38
0

You don't need use splice(). you can do it with using array swapping logic

Just use this as a key answer, I don't know it's exactly correct with your code :). I hope this logic will resolve your problem

//TopToBottom
flow3.moveItemDown = function moveItemDown()
    {
            var fromIndex = flow3.displayed.indexOf(flow3.selectedItem);
            if (fromIndex + 1 > flow3.displayed.length) {
                return false
            }
            var toindexObject = flow3.displayed[fromIndex + 1]
            flow3.displayed[fromIndex + 1] = flow3.selectedItem;
            flow3.displayed[fromIndex] = toindexObject;
    }

//BottomToTop
flow3.moveItemUp = function  moveItemUp() {
            var fromIndex = flow3.displayed.indexOf(flow3.selectedItem);
            if (fromIndex - 1 < flow3.displayed.length) {
                return false
            }
            var toindexObject = flow3.displayed[fromIndex - 1]
            flow3.displayed[fromIndex - 1] = flow3.selectedItem;
            flow3.displayed[fromIndex] = toindexObject;  
    }
Ramesh Rajendran
  • 37,412
  • 45
  • 153
  • 234
  • Hey Ramesh, thanks! For some reason the if (fromIndex + 1 > flow3.displayed.length) always true and it return false each time – ErEcTuS Jul 04 '17 at 12:39