React-dnd: Soporta arrastrar múltiples elementos

Creado en 25 oct. 2014  ·  30Comentarios  ·  Fuente: react-dnd/react-dnd

Existe un patrón común que es difícil de implementar con la función de arrastrar y soltar nativa: arrastrar varios elementos. Si bien la mecánica de selección puede variar de una aplicación a otra (cmd + clic, casillas de verificación, grupos predefinidos), sería bueno al menos hacer que sea _posible_ admitir este escenario.

screen shot 2014-10-26 at 1 07 07

Debido a que varios elementos arrastrados pueden no ser hermanos en DOM y setDragImage(element, x, y) es una locura y no ha mejorado, no nos preocuparemos por tratar de representar varios elementos en la vista previa de arrastre a la vez.

¿Cómo podemos ayudar a implementar este escenario, si no podemos mostrar una vista previa de arrastre "múltiple"?

En cierto modo, este escenario ya es posible: los consumidores pueden realizar un seguimiento manual de los elementos seleccionados, establecer dragPreview en algún tipo de marcador Image posición genérico

Sin embargo, actualmente no existe una forma compatible para que un elemento sepa que es parte de un grupo que se está arrastrando. Desde el punto de vista de react-dnd, si arrastramos algo, este componente obtiene getDragState(type).isDragging = true , pero otros componentes no. Desde el punto de vista de su aplicación, si admite la selección múltiple, desea que todos los elementos "seleccionados" lógicamente sepan que están siendo arrastrados, incluso si solo uno de ellos está siendo realmente "arrastrado por DOM".

Lo que necesitamos es una forma de que los componentes le digan a react-dnd que, "oye, aunque otro componente recibió onDragStart , quiero fingir que también me están arrastrando y tengo mi getDragState(type) espejo arrastró el componente getDragState(type) , y también se llamó a mi endDrag(didDrop) para poder hacer mis cosas ”.

¿Cómo optarían los componentes por eso?

design decisions

Comentario más útil

Si alguien está interesado, implementé una vista múltiple de arrastre / cuadrícula: https://codesandbox.io/s/9j897k0mwy.
Puede usar las teclas cmd / ctrl y shift para seleccionar varios elementos, luego arrastrarlos por la cuadrícula e insertarlos en cualquier lugar.

Esto sigue siendo una demostración, pero podría abstraer un poco más el código y empaquetarlo en un componente más adelante.

Todos 30 comentarios

No es una prioridad. Podemos volver a visitar después de introducir las claves de origen de arrastre (https://github.com/gaearon/react-dnd/issues/38#issuecomment-73409935).

Estaré interesado en esto en el futuro, aunque creo que podría simplemente envolver una sección de su árbol de componentes con un componente que tenga un dragSource ...
Por ejemplo, si mantiene presionada la tecla Mayús y hace clic, ¿qué secciones de la matriz se copian en el elemento de arrastre o algo así?

Un poco.

Primero aprendemos a pasar nulo component (necesario para # 38) y un componente diferente con el mismo key (necesario para # 53).

Luego agregamos groupKey que es opcional. Como key , se especifica en la fuente de arrastre y es una cadena. Cuando comience a arrastrar algo con groupKey , llamaremos beginDrag no solo a la persona que llama, sino a cada fuente de arrastre montada con el mismo groupKey , y reuniremos sus elementos en una matriz. Pasaremos estos elementos en lugar de item para eliminar los métodos de destino. Cuando finalice el arrastre, llamaremos acceptDrop en el destino de colocación con una matriz de elementos, y luego llamaremos endDrag cada fuente de arrastre con su elemento.

Lo que es divertido es que podemos dibujar DragLayer con un componente de miniatura "compuesto" personalizado y un contador como hice la captura de pantalla anterior porque sabemos el recuento de items.length .

Esa es una idea mucho menos fea de lo que tenía en mente.

: +1: para esta función :-)

Cerrando, ya que actualmente no tengo un caso de uso para esto, y es un esfuerzo de implementación significativo.

@gaearon

Usé Java / Swing DnD en el pasado, y probablemente tenían un ejército de desarrolladores que lidiaron con este problema y encontraron un marco bastante refinado, extremadamente genérico y flexible. Recomendaría investigar los marcos de escritorio antiguos, ya que probablemente resolvieron todos los desafíos difíciles de hacer un buen marco DnD como este.

La forma de hacer esto en Java / Swing (aunque no tenía soporte incorporado para imágenes de arrastre) era _hacer que la vista de árbol en sí misma fuera la fuente de arrastre_, y permitirle decidir si un arrastre debería iniciarse o no en función de su estado actual y la posición de inicio de arrastre_. ¿Está monitor.getInitialSourceClientOffset() disponible cuando se llaman canDrag y beginDrag ? La gente definitivamente querrá que esté disponible. Probablemente también deseen que las teclas modificadoras (ctrl, alt, shift) estén disponibles y que puedan hacer que las fuentes de arrastre especifiquen si se deben mover o copiar, y soltar objetivos para especificar si admiten mover y / o copiar, en función de cualquiera de estos factores, porque eso es posible en Java / Swing y supongo que en otros marcos. Swing también tenía el concepto de _reconocidores de gestos de arrastre_ que podían intercambiarse.

Yo predeciría que tratar todos los elementos de la lista como elementos de arrastre individuales será difícil en comparación con que el componente de la lista sea la única fuente de arrastre que determina qué tipo de carga útil / imagen de vista previa para soltar construir en función de lo que se selecciona en él.

Considere también que un desarrollador podría querer _cambiar el orden de los elementos que se arrastran según el elemento en el que el usuario hizo clic y desde el que los arrastró. Creo que el Explorador de Windows se comporta de esta manera.

¿Alguien ha implementado arrastrar varios elementos con react-dnd en sus aplicaciones? ¿Cuál es su solución actual para esto?

¿Quisiste decir destino de caída múltiple para una sola fuente de arrastre?

+1 @ danii1 : ¿Alguien ha implementado la función de arrastrar varios elementos?

Lo implementé, la solución es básicamente lo que se describe en la primera publicación:

  1. Mantenga un registro de sus artículos seleccionados
  2. Implemente CustomDragLayer (consulte https://gaearon.github.io/react-dnd/docs-drag-layer.html) y renderice los elementos seleccionados usted mismo
  3. Manejar la caída si el elemento caído es parte de la selección

Lo implementé por:

  1. Realizar un seguimiento de los elementos seleccionados en un conjunto
  2. Pase esto como una propiedad a la fuente dnd
  3. En beginDrag recupere el conjunto de los accesorios y devuélvalo como el elemento de arrastre
  4. Crear una vista previa de arrastre personalizada
  5. En EndDrag, mueva todos los elementos del conjunto al destino dnd

Creo que tengo un caso de uso ligeramente diferente para esto, quiero dibujar nodos que se puedan arrastrar con bordes que no se puedan arrastrar pero que se muevan cuando los nodos están conectados para moverse. Mi implementación actual es un CustomDragLayer que dibuja los bordes cuando detecta que un DraggableNode está moviendo (también dibujado en el CustomDragLayer pero creo que sería mejor modelarlo como un situación de arrastre múltiple implementando todos los bordes como DragSources con isDragging() implementado para detectar si un nodo al que están conectados se está moviendo para que puedan dibujarse a sí mismos en lugar de que los CustomDragLayer inyecten las coordenadas como accesorios .

@ danii1
¿Puede compartir el que ha implementado como referencia?

Escribiré una publicación y agregaré un repositorio sobre arrastrar y soltar múltiples y anidados con react-dnd + redux.

@nayemmajhar , sería genial

@nayemmajhar ¿ alguna actualización sobre un ejemplo con esto?

He desarrollado esta aplicación usando react DnD con reduxJS hace mucho tiempo https://www.joomshaper.com/page-builder Estoy escribiendo un tutorial pero necesito tiempo para publicar

@serle ¿Podrías compartir un ejemplo de código de cómo hiciste esto?

@ ianmclean2011 compruébalo aquí: https://github.com/react-dnd/react-dnd/issues/590

Estoy tratando de implementar arrastre múltiple en un ejemplo similar al ejemplo clasificable aquí: https://react-dnd.github.io/react-dnd/examples-sortable-simple.html. Quiero poder seleccionar cualquier objeto y luego moverlos como una unidad hacia arriba y hacia abajo en la lista. Tengo problemas para entender cómo usar los ejemplos / información compartidos anteriormente para hacer esto. ¿Algún pensamiento / idea / comentario sobre cómo podría funcionar esto?

Si alguien está interesado, implementé una vista múltiple de arrastre / cuadrícula: https://codesandbox.io/s/9j897k0mwy.
Puede usar las teclas cmd / ctrl y shift para seleccionar varios elementos, luego arrastrarlos por la cuadrícula e insertarlos en cualquier lugar.

Esto sigue siendo una demostración, pero podría abstraer un poco más el código y empaquetarlo en un componente más adelante.

@melvynhills ¿Ha investigado una solución que no requiera pasar todas las tarjetas seleccionadas a cada componente de la tarjeta? No creo que haya una solución considerando que beginDrag () de la tarjeta necesita una referencia a todas las tarjetas seleccionadas.

@jmcrthrs No, no me parece posible con la API react-dnd. No creo que haya una forma de saber antes de arrastrar qué elemento específico se va a arrastrar. Esa es también la única forma de saber si el elemento arrastrado está dentro de la selección múltiple que realizó, o si está fuera de esa selección que luego debemos reemplazar.

@melvynhills @jmcrthrs otros frameworks dnd de escritorio que he usado se basan en hacer listas y tablas como fuentes de arrastre / destinos de colocación en lugar de hacer que cada fila, celda, elemento, etc. individual sea su propia fuente de arrastre y / o destino de colocación. La implementación para arrastrar varios elementos, así como para obtener la ubicación de colocación específica dentro de la lista o tabla, resulta mucho más limpia de esa manera. Cuando una lista recibe un evento de inicio de arrastre, simplemente puede mirar sus elementos seleccionados actualmente.

@ jedwards1211 ¿cree que es factible con esta biblioteca? Especialmente el caso de uso de comenzar a arrastrar un elemento que no se seleccionó antes de que comenzara el arrastre. No estoy seguro de que sea la forma en que se supone que funciona react-dnd.

¿Alguien ha resuelto el caso en el que hay varios objetivos de caída?
Digamos que uno está arrastrando varios elementos (usando una de las soluciones anteriores) y un elemento termina en un tipo de destino de colocación y el otro en el diferente. drop se activará solo para la fuente de arrastre que inició el arrastre, pero no para la otra. Cualquier idea sobre cómo desencadenar la caída individual para cada elemento que se mueve.
Ejemplo:
Is development slow, Online Whiteboard for Visual Collaboration 2019-11-27 10-45-33

EDITAR: Se creó un problema separado para este https://github.com/react-dnd/react-dnd/issues/1650

@melvynhills probablemente si un controlador mousedown activa la selección de elementos (lo que debería estar haciendo, todo el software con DnD que he usado funciona de esta manera), funcionará bien con React DnD para que el componente contenedor sea el arrastre source, porque los eventos de arrastre vendrán después de mousedown .

¿Ha investigado una solución que no requiera pasar todas las tarjetas seleccionadas a cada componente de la tarjeta?

Este es un ejemplo de por qué recomendaría hacer que el componente contenedor sea la fuente de arrastre en lugar de los elementos individuales. No he necesitado implementar multiselect con React DnD, pero tal vez en algún momento pueda hacer una caja de arena para convencer a la gente de que es el enfoque más fácil de mantener.

¿Alguien ha implementado arrastrar varios elementos con react-beautiful-dnd en sus aplicaciones? ¿Cuál es su solución actual para esto?

¿Fue útil esta página
0 / 5 - 0 calificaciones