Not sure if this would be doing some work in cdk/drag-drop
that will make it automatically work on the tabs, or if a supplemental directive would be necessary.
Some of my thoughts:
cdk/drag-drop
If we want something that “just works”, we’ll need some kind of abstraction around the mat-tab-group since we don’t have access to the data that’s driving the tabs and the consumer doesn’t have direct access to the tab label itself.
It doesn't necessarily have to work without the user doing anything extra, there just needs to be a supported (documented) way of doing it.
I see. In that case we definitely need some kind of alternate API for the drag&drop that works with generated elements since the tabs work by taking the content, putting it in an ng-template
and stamping out the content some place else.
Another thing that came up: dragging tabs between groups
@crisbeto This is a very simple implementation without coupling
https://stackblitz.com/edit/angular-mgrsxx-tfeye2?file=app/tab-group-basic-example.ts
Notes:
Thanks a lot! Indeed our use case does involve moving tabs between tab groups, so will look forward to those two being resolved as well!
@mtaran-google this use case is in most part supported...
Here's a rough POC: https://stackblitz.com/edit/angular-mgrsxx-tzpqjc?file=app%2Ftab-group-basic-example.html
Currently, there are 2 bugs I know of:
The 2nd issue also causes the drop area to be the entire mat-tab-group
because it's not possible to pinpoint a specific container area inside the drop container.
Both issues have temp workaround via directives i've wrapped around CdkDrag
and CdkDropList
...
Other than that all bugs and issues in this POC are solvable with some work on solid wrapper directives that know how to work with the tabs. Maybe some API is required to allow programmatic control over the tabs...
Anyway, I think that each and every CDK components must come with an extensive API that allows complete programmatic control, this is a must.
In angular, your end goal is to work with templates as much as possible, because more template -> less code -> fewer bugs.
But this is true for apps, not for low level components, having extensive API in the low-level components will lead to applications with less code.
I managed it with 7.2 using CDK library:
<mat-tab-group style="position: absolute; background-color: aqua;top: 0;">
<mat-tab *ngFor="let view of views; let i = index">
<ng-template mat-tab-label>
<div [id]="'list-'+i" class="drag-list" cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="drop($event)" [cdkDropListConnectedTo]="getAllListConnections(index)">
<div class="drag-box" cdkDrag>{{view}}</div>
</div>
</ng-template>
Content {{view}}
</mat-tab>
</mat-tab-group>
getAllListConnections(index){
var connections = []
for(var i=0;i<views.length;i++){
if(i!=index){
connections.push("list-"+i);
}
}
return connections;
}
md5-f4236d0d21270d137569f7065edaf61f
drop(event: CdkDragDrop<string[]>) {
var previousIndex = parseInt(event.previousContainer.id.replace("list-",""));
var currentIndex = parseInt(event.container.id.replace("list-",""));
if(previousIndex!=NaN && currentIndex!=NaN && previousIndex!=undefined && currentIndex!=undefined && previousIndex!=currentIndex){
//Do stuff
.....
//END Stuff
moveItemInArray(this.views, previousIndex, currentIndex);
}
}
Hope it helps
This works nicely - many thanks. But curiously it seems to kill the isActive flag on the tabs.
is there any progress?
The necessary APIs for this were added in https://github.com/angular/material2/pull/14437, but we haven't gotten around to writing a guide for it yet.
Are there are updates wrt documentation for this?
@MiguelRozalen thanks, your solution works great !
I'm sorry to ask that here but I have an issue that I don't manage to solve : tabs are not reorder dynamically when I'm dragging one tab... (See the expected behaviour here : https://stackblitz.com/edit/angular-kwwarq?file=app%2Fcdk-drag-drop-horizontal-sorting-example.css)
Did you find a way to reorder dynamically the list when you are dragging one tab ?
Are there any updates regarding documentation for drag&drop mat tabs?
Hi @MiguelRozalen can you maybe help me with your implementation Stackoverflow question , do you maybe have idea why this is not working ?
Are there any updates regarding documentation for drag&drop mat tabs?
:D
+1
Any update on this?
Found a working solution:
<mat-tab-group
[selectedIndex]="currentStep"
(selectedIndexChange)="currentStep = $event; updateConnectedTo();"
style="position: relative; z-index: 0;"
>
<mat-tab
*ngFor="let step of wizard?.components; let stepIndex = index"
>
<ng-template mat-tab-label>
<div
[id]="'list-' + stepIndex"
class="steps-drag-list"
cdkDropList
cdkDropListOrientation="horizontal"
(cdkDropListDropped)="dropStep($event)"
[cdkDropListConnectedTo]="getAllListConnections(stepIndex)">
<div
class="step-drag-box"
cdkDrag
[cdkDragDisabled]="stepIndex === wizard?.components?.length - 1"
>
{{step.title}}
<div
cdkDragHandle
*ngIf="stepIndex < wizard?.components?.length - 1
&& this.currentStep === stepIndex"
>
<mat-icon class="move-step">open_with</mat-icon>
</div>
</div>
</div>
</ng-template>
<div>
{{step}}
</div>
</...>
```
getAllListConnections(index){
var connections = [];
for(var i=0; i < this.wizard?.components?.length; i++){
if(i != index){
connections.push("list-" + i);
}
}
return connections;
}
dropStep(event: CdkDragDrop
const currentIndex = parseInt(event.container.id.replace("list-",""));
if(currentIndex >= this.wizard?.components?.length - 1)
{
this.snackBar.open(
"You cannot put steps after Confirmation Step!",
"DISMISS",
{
duration: 3000,
}
);
return;
}
if ( previousIndex != NaN
&& currentIndex != NaN
&& previousIndex != undefined
&& currentIndex != undefined
&& previousIndex != currentIndex
){
moveItemInArray(this.wizard?.components, previousIndex, currentIndex);
let aux = JSON.stringify(this.wizard, this.ignoreNull, ' ');
this.wizard = JSON.parse(aux); // Needed to avoid Angular Ivy render bug
this.currentStep = this.wizard?.components?.find((step, i) => currentIndex === i)
? currentIndex
: 0;
}
}
```
Hey! @AlvaroP95 can you please share stackblitz solution as this code is not working for me.
Thanks in advance!
Most helpful comment
Are there are updates wrt documentation for this?