Sean
Sean

Reputation: 15144

Angular CDK Drag/Drop List with table-body / rows distorting width (without Material)

I'm using a plain (Bootstrap) table which I want to have sortable rows on. I'm using the Angular CDK (DragDropModule) to implement sorting / ordering. However, when the row gets dragged, it distorts the width, as the cdkDragPreview (tr element) is now outside the table, appended to the body, so it has a different display style and the column widths wouldn't match with the original table even if it was display:table.

Here's the rough html:

  <table>
    <thead>
      <tr>
        <th><i class="fas fa-sort mt-1"></i></th>
        <th>Code</th>
        <th>Name</th>
        <th>Date Type</th>
      </tr>
    </thead>
    <tbody cdkDropList (cdkDropListDropped)="drop($event)">
      <tr *ngFor="let date of dates" cdkDrag>
        <td cdkDragHandle><i class="fas fa-sort mt-1"></i></td>
        <td>{{ date.code }}</td>
        <td>{{ date.name }}</td>
        <td>{{ date.dateType }}</td>
      </tr>
    </tbody>
  </table>

How do I get the dragging/ordering to 'look good'?

Upvotes: 3

Views: 5663

Answers (3)

Flor Fina
Flor Fina

Reputation: 11

Setting display:flex; to the table row in the cdk drag preview worked in my case.

<style>
        tr.cdk-drag-preview {
            display: flex;
            align-items: center;
            min-width: 170px;
            padding: 0.25rem;
            box-shadow: 0.125rem 0.125rem 0.25rem rgba(0, 0, 0, 0.2);
        }
        
        /* can be optional in some cases */
        tr.cdk-drag-preview td:nth-last-child(1) {
            flex: 1 0 auto;
        }
</style>

I also had to set flex: 1 0 auto; to the penultimate column.

Upvotes: 1

trungvose
trungvose

Reputation: 20034

I ended up to set the column width manually.

See the working example: https://angular-cdk-drag-drop-bootstrap-table.stackblitz.io

Result

Angular CDK Drag/Drop List inside table (not Material Table) - Handle rows distorting width

.col-xs {
  width: 2%;  
}

.col-sm {
  width: 10%;  
}

.col-md {
  width: 20%;  
}
<tbody cdkDropList
        (cdkDropListDropped)="onDrop($event)">
    <tr *ngFor="let user of users"
        cdkDrag
        cdkDragLockAxis="y">
        <th class="col-xs">
            <div class="drag-handle">
                <ng-container [ngTemplateOutlet]="dragHandleTmpl">
                </ng-container>
                {{ user.order }}
            </div>
        </th>
        <td class="col-md">{{ user.first }}</td>
        <td class="col-md">{{ user.last }}</td>
        <td class="col-md">{{ user.email }}</td>
        <td class="col-md">{{ user.address }}</td>
    </tr>
</tbody>

Upvotes: 2

Sean
Sean

Reputation: 15144

I've ended up NOT using a drag preview (cdkDragPreview) as that's too difficult to get the columns widths right. Instead, I simply set the cdkDragPreview to an empty element so nothing shows, and let the user see the actual (underlying) sort, rather than the preview.

So, simply:

  <table>
    <thead>
      <tr>
        <th><i class="fas fa-sort mt-1"></i></th>
        <th>Code</th>
        <th>Name</th>
        <th>Date Type</th>
      </tr>
    </thead>
    <tbody cdkDropList (cdkDropListDropped)="drop($event)">
      <tr *ngFor="let date of dates" cdkDrag>
        <td cdkDragHandle><i class="fas fa-sort mt-1"></i><span *cdkDragPreview></span></td>
        <td>{{ date.code }}</td>
        <td>{{ date.name }}</td>
        <td>{{ date.dateType }}</td>
      </tr>
    </tbody>
  </table>

If anyone can find a good, easy way of getting the column widths right, that would be ideal...

Upvotes: 4

Related Questions