15

I have created a grid in dgrid that is connected to JsonRest store. This loads data from pyramid backend. I have also added DnD extension to the store. The DnD works, however I don't know how to make it send any meaningful data when I drag the rows. Currently it sends two requests, one GET and one PUT, but the PUT contains just the data from rows but nothing that I could use to update the order in the database.

So what configuration is necessary in my grid, so that I can get the new ordering information?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
zefciu
  • 1,967
  • 2
  • 17
  • 39
  • Hi, have you figured this one yet ? I came across the same issue today. – noru Mar 21 '13 at 07:01
  • 1
    I fear, that this would require subclassing the store, however let's try with a bounty. – zefciu Mar 21 '13 at 10:32
  • 3
    Could you provide a jsfiddle ? – Lucian Depold Mar 27 '13 at 07:00
  • 2
    What is your intent when you drag the rows? Presumably the data in the Db is ordered by some field. If you drag the rows then you need to update that field to give a new order, which implies that if say you drag "7" to before "5" then 7 becomes 5, 5 becomes 6 and 6 becomes 7. Is that your intention? My instinct is that you need to update the data in the store to relect this change, and then trigger the updates. – djna Apr 03 '13 at 09:34
  • The approach I take is exactly as @djna describes. See my answer below for details. – Ali Gangji May 27 '13 at 02:30

1 Answers1

3

This is what I do:

  1. maintain a position column in the database
  2. call store.put when a row is dropped, passing the id of the dropped item and the position it was dropped at.
  3. When updating the position, shift the other items accordingly

Here is my onDropInternal function. It handles dropping multiple rows as well:

        onDropInternal: function(nodes, copy, targetItem) {

            var store = this.grid.store, grid = this.grid, targetRow, targetPosition;

            if (!this._targetAnchor) return

            targetRow = grid.row(this._targetAnchor);
            targetPosition = parseInt(targetRow.data[grid.orderColumn]);
            responses = 1;

            nodes.forEach(function(node, idx){
                targetPosition += idx;
                var object = {id:grid.row(node).id};
                object[grid.orderColumn] = targetPosition;
                store.put(object).then(function() {
                        if (responses == nodes.length) grid.refresh();
                        else responses++;
                });
            });

        }

Here's the PHP code I used to update the position. $fields is an associative array representing the record to store. It also assumes the existence of two functions: query and query_row, which I trust you can handle replacing if you choose to utilize this technique.

$table = "my_table";
$field = "position_field";
if (empty($fields['id'])) {
    //for new records, set the position field to the max position + 1
    $h = query_row("SELECT MAX(`$field`) as highest FROM $table LIMIT 1");
    $fields[$field] = $h['highest']+1;
} else if (is_numeric($fields[$field])) {
    //we want to move the row to $target_position
    $target_position = $fields[$field];
    //first get the original position
    $row = query_row("SELECT id,$field FROM $table WHERE id='$fields[id]' LIMIT 1");
    //start a list of ids
    $ids = $row['id'];
    //if the original position is lower than the target postion, set the incrementor to -1, otherwise 1
    $increment = ($row[$field] < $target_position) ? -1 : 1;
    //start a while loop that goes as we long as we have a row trying to take a filled position
    while (!empty($row)) {
        //set the position
        query("UPDATE $table SET $field='$target_position' where id='$row[id]'");
        //get the other row with this position (if it exists)
        $row = query_row("SELECT id,$field FROM $table WHERE id NOT IN ($ids) && `$field`='$target_position' LIMIT 1");
        //add it's id to the list of ids to exclude on the next iteration
        $ids .= ", ".$row['id'];
        //increment/decrement the target position
        $target_position += $increment;
    }
}

You could probably make this more efficient by using a query that updates multiple records at once, but the advantage of this is that it handles unexpected gaps in position numbers well.

Ali Gangji
  • 1,463
  • 13
  • 22