Evitar la caída del elemento de la lista en JqueryUI ordenable

4 minutos de lectura

avatar de usuario de user1038814
usuario1038814

tengo dos listas #sortable1 y #sortable 2 que son ordenables conectados, como se muestra en este ejemplo.

Puede arrastrar y soltar elementos de la lista desde sortable1 a sortable 2. Sin embargo, si un artículo en ordenable 1 contiene la clase “número”, quiero prevenir la gota en Ordenable2 y así hacer que el elemento arrastrado vuelva a caer en ordenable 1.

He usado lo siguiente en sortable2:

receive: function (event, ui) {
            if ($(ui.item).hasClass("number")) {
                $(ui.item).remove();
            }

pero elimina el elemento de la lista de ambas tablas por completo. Cualquier ayuda será apreciada.

Avatar de usuario de TJ
T.J.

Para cualquiera que lea esto en el futuro, como lo menciona briansol en los comentarios de la respuesta aceptada, arroja un error

Uncaught TypeError: Cannot read property 'removeChild' of null

La documentación dice particularmente

cancel()

Cancela un cambio en la ordenación actual y lo revierte al estado anterior al inicio de la ordenación actual. Útil en el deténgase y recibir funciones de devolución de llamada.

Cancelar la clasificación durante otros eventos no es confiable, por lo que es mejor usar el receive evento como se muestra en la respuesta de Mj Azani o use el stop evento de la siguiente manera:

$('#list1').sortable({
  connectWith: 'ul',
  stop: function(ev, ui) {
    if(ui.item.hasClass("number"))
      $(this).sortable("cancel");
   }
}); 

$('#list2').sortable({
   connectWith: 'ul',
});  

Manifestación

Avatar de usuario de Richard
Ricardo

Puede utilizar una combinación de los stop y sortable('cancel') métodos para validar el elemento que se está moviendo. En este ejemploal dejar caer un artículo, compruebo si el artículo es válido:

  1. Comprobando si el artículo tiene la clase. number
  2. y comprobar si el elemento de la lista se dejó caer en list2

Esto está un poco más codificado de lo que me gustaría, por lo que, alternativamente, lo que podría hacer es verificar el padre del elemento soltado contra this, para comprobar si las listas son diferentes. Esto significa que potencialmente podría tener un artículo de number en list1 y list2pero no son intercambiables.

Ejemplo de jsFiddle

$(function() {
    $('ul').sortable({
        connectWith: 'ul',
        stop: function(ev, ui) {
            if ($(ui.item).hasClass('number') && $(ui.placeholder).parent()[0] != this) {
                $(this).sortable('cancel');
            }
        }
    });        
});​

  • Usando este método, parece que obtengo errores JS. Actualicé un informe de error en el sitio jQUI que puede estar relacionado. bugs.jqueryui.com/ticket/4904?cnum_edit=9#comentario:9

    – BReal14

    07/03/2014 a las 19:10


  • cancel solo es confiable en el stop y receive eventos como se menciona en esta otra respuesta

    – NDM

    20 de agosto de 2015 a las 10:47

  • this.sortable no funcionó para mí, pero al cambiar a ui.sender.sortable (“cancelar”); la identificación funciona perfectamente

    – Mimouni

    26 de mayo de 2016 a las 9:12

  • Obteniendo un error: TypeError no detectado: no se puede leer la propiedad ‘removeChild’ de null. Rompe el sortable…

    – Loenix

    21 de marzo de 2017 a las 4:49

  • @ Mr.Jo He actualizado el ejemplo anterior para resolver el error.

    – Ricardo

    28 de junio de 2021 a las 18:48


Avatar de usuario de Mj Azani
Mj Azani

Probar este ejemplo

$('#list1').sortable({
    connectWith: 'ul'
});    

$('#list2').sortable({
    connectWith: 'ul',
    receive: function(ev, ui) {
        if(ui.item.hasClass("number"))
          ui.sender.sortable("cancel");
    }
});    

Después de algunos experimentos, descubrí que, con mucho, el método más fácil es usar el evento de eliminación, que esencialmente solo se activa cuando intenta colocar un elemento en una nueva clasificación (que anteriormente estaba disponible como objetivo usando connectWith).

Simplemente agregue esto a su llamada ordenable:

remove:function(e,ui) {
    if(ui.item.hasClass('your_restricted_classname')) return false;
},

Si no necesita poder arrastrar los elementos con el “número” de clase, también puede restringir toda la funcionalidad de arrastrar y soltar a los elementos que no tienen el “número” de clase:

$("#sortable1, #sortable2").sortable({
    connectWith: ".connectedSortable",
    items: "li:not(.number)"
});

Puedes probarlo aquí: http://jsfiddle.net/60gwjsgb/1/

Avatar de usuario de TanvirChowdhury
TanvirChowdhury

beforeStop: function(ev, ui) {
                if ($(ui.item).hasClass('number') && 
                    $(ui.placeholder).parent()[0] != this) {
                    $(this).sortable('cancel');
                }
            }

prueba esto.

Avatar de usuario de Narges Ahani
Narges Ahani

Si a) solo tiene estas 2 listas, yb) no le importa que su “número” se arrastre y luego vuelva a caer, simplemente puede evitar que sea arrastrado por esto:

 sort: function(event, ui) {
if(ui.item.hasClass('number')) return false;
}

¿Ha sido útil esta solución?