3

Having trouble with knockout js. But seems to me it's a bug. Maybe there are some workaround.

There is an example of sorting list here and it works. And there is another example and it doesn't. The only difference between them is version of KO.

Any help would be appreciated.

Update: I don't know the reason but after calling splice method KO refreshes binding in some incorrect way. So the workaround I've found - force rebind array model.

The code I use to force rebinding is follows:

        // newArray is ko.observableArray([...])
        var original = newArray();
        newArray([]);
        newArray(original); // KO will rebind this array

Is there more elegant way to force rebinding?

1
  • I'm not sure what you are expecting, but I see exactly the same behaviour in both pages. Commented Jun 11, 2012 at 11:01

1 Answer 1

4

I believe what is happening here is that Knockout 2.1 is correctly updating the list when you splice the new item into it, but the jQuery UI sortable implementation is also adding the item to the new list.

To get around this I added a 'dragged' class to the item that gets added by the sortable implementation, and then removed it once I updated the two arrays (which causes the UI update as expected).

    $list
      .data('ko-sort-array', array)
      .sortable(config)
      .bind('sortstart', function (event, ui) {                  
        ui.item.data('ko-sort-array', array);
        ui.item.data('ko-sort-index', ui.item.index());
        ui.item.addClass('dragged'); // <-- add class here
      })
      .bind('sortupdate', function (event, ui) {
        var $newList = ui.item.parent();
        if($newList[0] != $list[0]){ return; }

        var oldArray = ui.item.data('ko-sort-array');
        var oldIndex = ui.item.data('ko-sort-index');

        var newArray = $newList.data('ko-sort-array');
        var newIndex = ui.item.index();

        var item = oldArray.splice(oldIndex, 1)[0];
        newArray.splice(newIndex, 0, item);
        $list.find('.dragged').remove(); // <-- remove the item added by jQuery here
      });

You can see this working here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.