Me gustaría usar DragDropModule para mi aplicación angular para poder mover paneles que están almacenados dentro de plantillas (para fines prácticos, así como para el trazado recursivo de elementos secundarios).
El problema que tengo es que cdkDrag no puede encontrar el cdkDropList correcto para colocar si cdkDrag está oculto dentro de una plantilla y no está anidado directamente debajo del elemento HTML. Ejemplo:
<div cdkDropList [cdkDropListData]="expanded.activities" (cdkDropListDropped)="dropActivity($event)"> <div *ngFor="let activity of expanded.activities"> <ng-container [ngTemplateOutlet]="orangeProgramActivity"></ng-container> </div> </div> <ng-template #orangeProgramActivity> <div cdkDrag>This is just a test</div> </ng-template>Con este ejemplo de código, orangeProgramActivity se puede arrastrar a cualquier lugar, pero no se coloca en la lista desplegable correcta, ya que la palabra clave cdkDrag no puede encontrar ninguna lista desplegable dentro de su propia plantilla.
En el segundo ejemplo, todo funciona correctamente y el elemento se coloca en la lista desplegable correcta:
<div cdkDropList [cdkDropListData]="expanded.activities" (cdkDropListDropped)="dropActivity($event)"> <div *ngFor="let activity of expanded.activities"> <div cdkDrag>This is just a test</div> </div> </div>Me gustaría lograr la misma funcionalidad que en el segundo ejemplo, pero con el uso de plantillas porque realmente las necesito para la recursividad. Desafortunadamente, no puedo revelar el código completo ya que mi empleador no estaría contento con eso.
Todo lo que necesito es alguna referencia estática para mi cdkDrag que está dentro de una plantilla, para apuntar a un elemento correcto con dropList que está fuera de la plantilla.
Estas son las únicas soluciones que encontré en Internet y no parecen funcionar para mí: Material 7 Arrastrar y soltar ng-template incompatibilidad CdkDragDrop y ngTemplateOutlet
Esta es mi primera pregunta sobre Stack Overflow y soy nuevo en angular, por lo que lamento cualquier confusión en mi publicación y gracias por cualquier ayuda de antemano.
Es posible que esto no funcione para todos los casos de uso, pero podría escribirlo así:
<div cdkDropList [cdkDropListData]="expanded.activities" (cdkDropListDropped)="dropActivity($event)"> <div *ngFor="let activity of expanded.activities" cdkDrag> <ng-container [ngTemplateOutlet]="orangeProgramActivity"></ng-container> </div> </div> <ng-template #orangeProgramActivity> <div>This is just a test</div> </ng-template>Tuve la suerte de que solo necesito reordenar elementos dentro de una matriz en la que están y no necesito transferirlos a otros contenedores. Entonces, para mis actividades "raíz", usé su solución simple para envolverlo todo en un elemento arrastrable.
<div cdkDropList [cdkDropListData]="expanded.activities" (cdkDropListDropped)="dropActivity($event)"> <!-- For every object in array make a container with template and an icon that will serve as a handle --> <div *ngFor="let activity of expanded.activities"> <div cdkDrag> <div cdkDragHandle> <!-- Handle icon from FontAwesome --> <i class="fas fa-grip-vertical"></i> </div> <!-- Container with a template that we need --> <ng-container [ngTemplateOutlet]="orangeProgramActivity" [ngTemplateOutletContext]="{act: activity}"></ng-container> </div> <!-- Recursive template for children --> <ng-container [ngTemplateOutlet]="childActivitiesRecursion" [ngTemplateOutletContext]="{act: activity}"></ng-container> </div>Y para mi recursión , creé una lista desplegable dentro de una plantilla que solo sirve para reordenar las actividades de estos niños. (Tuve problemas al pegar la plantilla, por lo que la etiqueta ng-template no finaliza al final del código)
<ng-template let-act="act" #childActivitiesRecursion> <!-- Droplist inside a template for reordering child activites --> <div cdkDropList [cdkDropListData]="act.childActivities" (cdkDropListDropped)="dropActivity($event)"> <!-- Iterates through all child activities --> <div *ngFor="let childActivity of act.childActivities"> <div cdkDrag> <div cdkDragHandle> <i class="fas fa-grip-vertical"></i> </div> <!-- Different template for child activities --> <ng-container [ngTemplateOutlet]="blueProgramActivity" [ngTemplateOutletContext]="{act: childActivity}"></ng-container> </div> <!-- Recursion for even deeper child activites --> <ng-container [ngTemplateOutlet]="childActivitiesRecursion" [ngTemplateOutletContext]="{act: childActivity}"></ng-container> </div> </div>Aceptaré la respuesta de Richard como una solución porque si puede resolverlo de esta manera, definitivamente es la solución más elegante que puede hacer. ¡Pero aún habría un problema si necesita transferir elementos a diferentes contenedores después de usar plantillas para la recursividad!