Skip to content
This repository was archived by the owner on Sep 8, 2020. It is now read-only.
This repository was archived by the owner on Sep 8, 2020. It is now read-only.

canceling drag between connected lists drops item #107

Closed

Description

@brendanblackwood

I'm trying to cancel dragging an item from one list to another if certain conditions are met (in the example, max list size).

http://codepen.io/anon/pen/toDej

Try to have more than 10 things in one of the lists. Visually, there are no problems, but if you log out the results, you see items are getting removed from one list and not put back. It could be that I'm approaching this wrong, but I'm running out of ideas.

Oh, and I am using the angular1.2 branch.

Activity

  1. thgreasi commented on Jan 29, 2014

    @thgreasi
    Contributor

    You should use the model to count the length of the list, not the DOM elements.

  2. ghost assigned on Jan 29, 2014
  3. brendanblackwood commented on Jan 29, 2014

    @brendanblackwood
    Author

    Fair enough. The same problem will persist, however. Canceling the sort will replace the item in the proper place in the DOM, but it will not replace the model. That just gets lost.

    New codepen with model checking: http://codepen.io/anon/pen/fAvCJ

  4. thgreasi commented on Jan 29, 2014

    @thgreasi
    Contributor

    Here is the order that the events fire on connected lists:

    strart      0
    activate    1
    activate    0
    update      0
    remove      0
    receive     1
    update      1
    stop        0
    

    As far as I know the best time to call cancel() is inside the first update callback. Receive and update on the receiving list is too late, since the first model has already been altered.
    Here is a pen utilizing the changes of #108.

    Feel free to reopen if necessary.

  5. brendanblackwood commented on Jan 30, 2014

    @brendanblackwood
    Author

    Works great. Thanks!

  6. jegesh commented on Mar 14, 2016

    @jegesh

    How would I go about cancelling a drag between lists, but allowing ordering within a list, only for certain elements (validation)? When I try to cancel when remove fires from the original list, the element stays put, but becomes unorderable thereafter. Debugging it, I see that ui.item.sortable.model is undefined.

  7. thgreasi commented on Mar 14, 2016

    @thgreasi
    Contributor

    You can place your logic in the update callback and use the properties of
    the ui.item.sortable object (ui is the second argument of the callback).
    Take a look at the examples and documentation in README.md and API.md .

    Thodoris Greasidis
    Computer, Networking &
    Communications Engineer

  8. jegesh commented on Mar 14, 2016

    @jegesh

    I tried doing that, but I need to know if it's just a sort within the list, or moving to a second list. There is no indication of this until either the second update is hit, or remove of the first list gets hit, in either too late to cancel the action, because the update call of the original list happens before that. I'm looking for a way to either determine already in the first update if it's a move or an ordering, or alternatively a way to 'manually' call the update callback from within the remove callback of the same list.

  9. thgreasi commented on Mar 14, 2016

    @thgreasi
    Contributor

    As noted in API.md, you can use the droptarget and droptargetModel properties and possibly compare them with source and sourceModel properties, to check whether it's a connected-list sorting.

  10. thgreasi commented on Mar 14, 2016

    @thgreasi
    Contributor

    The comparison of droptarget should look like source[0] !== droptarget[0] since both of them are jQuery Collection Objects.
    An other of doing this would be by using the moved property (even though I don't prefer it and it might get deprecated).

  11. jegesh commented on Mar 15, 2016

    @jegesh

    I'm sorry, maybe I'm dense, but I feel like you didn't read my last comment very closely. The problem I'm having is with the timing of the cancellation. If I cancel after I know if it's a reorder or a move, then the source list has already been updated, and cancelling producing the situation mentioned by the PO above, wherein the draggable is neither here nor there - it appears to be in the list, but it's missing from the sourceModel array. So I need to postpone the update until I know if it's a move or just a reorder, and then fire it, or decide not to.

  12. thgreasi commented on Mar 15, 2016

    @thgreasi
    Contributor

    Please provide an example of your use case by forking one of the codepen
    examples found in README and I will do my best to help you. If delayed
    cancellation is all that you need, you can take a look at the "promised
    cancellation" example.

    Thodoris Greasidis
    Computer, Networking &
    Communications Engineer

  13. jegesh commented on Mar 16, 2016

    @jegesh

    Thank you so much for your assistance. Examining the 'promised cancellation' example I was able to come up with a satisfactory workaround. I'm posting my code in case it might be of help to someone else in the future:

    var _immovableItem = null;
    $scope.sortableOptions.list1 = {
              connectWith:".list2",
              activate: function(){
                _immovableItem = null;
              },
              remove: function(e, ui){
                if (isInvalid(ui.item.sortable.model) {
                  ui.item.sortable.cancel();
                  _immovableItem = ui.item.sortable.model;
                }
              },
              stop: function(e, ui){
                if (_immovableItem) {
                  ui.item.sortable.sourceModel.push(_immovableItem);
                  $timeout(function(){
                    $(e.target).find("li").last().remove();
                  });
                }
              }
            };
            $scope.sortableOptions.list2 = {
              connectWith: ".list1",
              update: function (e, ui) {
                if(isInvalid(ui.item.sortable.model)){
                  ui.item.sortable.cancel();
                }
              }
            };
    

    Essentially, what's happening here is that in the first list, where I want to keep items that don't pass validation but allow them to be reordered within it, I perform validation on every update. If the item doesn't pass validation, I store it in the _immovableItem variable for later use. Then, if the item gets removed from that first list, I know the user is attempting to move it, which I don't want to allow, therefore I cancel the remove (which only prevents it from being removed from the DOM of the first list, but not the data model), cancel the update into the second list, and after everything has settled down (i.e. in a $timeout function), manually add the item back to the data model of the first list, and manually remove the orphaned <li> left over at the end of the list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions