drag and drop data table - rppowellemail/angular-step-by-step GitHub Wiki
- https://javascript.plainenglish.io/beautiful-styling-for-drag-and-drop-rows-in-the-angular-datatable-6870768c5a8f
- https://github.com/matteson/drag-drop-data-table
Create Basic Apps
ng new draggable-data-table
Example using defaults:
? Do you want to enforce stricter type checking and stricter bundle budgets in the workspace?
This setting helps improve maintainability and catch bugs ahead of time.
For more information, see https://angular.io/strict No
? Would you like to add Angular routing? No
? Which stylesheet format would you like to use? CSS
Start and run:
cd draggable-data-table
ng serve
View at:
Install modules:
npm install --save @angular/material
npm install --save @angular/cdk
npm install --save @angular/flex-layout
Add modules to src\app\app.module.ts
:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
As so:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FlexLayoutModule } from '@angular/flex-layout';
import { AppComponent } from './app.component';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { MatTableModule } from '@angular/material/table';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
DragDropModule,
MatTableModule,
FlexLayoutModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Edit src\app\app.component.ts
and change:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'draganddrop-data-table';
}
To:
import { Component } from '@angular/core';
export interface PeriodicElement {
name: string;
weight: number;
symbol: string;
}
const ELEMENT_DATA: PeriodicElement[] = [
{name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
{name: 'Helium', weight: 4.0026, symbol: 'He'},
{name: 'Lithium', weight: 6.941, symbol: 'Li'},
{name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
{name: 'Boron', weight: 10.811, symbol: 'B'},
{name: 'Carbon', weight: 12.0107, symbol: 'C'},
{name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
{name: 'Oxygen', weight: 15.9994, symbol: 'O'},
{name: 'Fluorine', weight: 18.9984, symbol: 'F'},
{name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
displayedColumns: string[] = ['name', 'weight', 'symbol'];
dataSource = ELEMENT_DATA;
}
Replace contents of src\app\app.component.html
with:
<div fxFlex fxLayout="row wrap">
<div fxFlex="5"></div>
<div fxFlex="50" class="mat-elevation-z8">
<table mat-table
#dataTable
fxFlex
[dataSource]="dataSource">
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}}
</td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef> Weight </th>
<td mat-cell *matCellDef="let element"> {{element.weight}}
</td>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="symbol">
<th mat-header-cell *matHeaderCellDef> Symbol </th>
<td mat-cell *matCellDef="let element"> {{element.symbol}}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row
*matRowDef="let row;
columns: displayedColumns;"></tr>
</table>
</div>
<div fxFlex="45"></div>
</div>
Adding some styling to src\app\app.component.css
:
.cdk-drag-preview {
box-sizing: border-box;
border-radius: 4px;
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px
rgba(0, 0, 0, 0.14), 0 3px 14px 2px
rgba(0, 0, 0, 0.12);
height: 48px;
background-color: white;
display: table;
}
.cdk-drag-preview td {
flex-grow: 2;
font-size: 14px;
padding: 4px;
vertical-align: middle;
}
.cdk-drag-placeholder {
background-color: grey;
}
.cdk-drag-animating {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
.cdk-drop-list-dragging .mat-row:not(.cdk-drag-placeholder) {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
Adding Drag and Drop
to src\app\app.component.html
, before:
<div fxFlex fxLayout="row wrap">
<div fxFlex="5"></div>
<div fxFlex="50" class="mat-elevation-z8">
<table mat-table
#dataTable
fxFlex
[dataSource]="dataSource">
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}}
</td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef> Weight </th>
<td mat-cell *matCellDef="let element"> {{element.weight}}
</td>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="symbol">
<th mat-header-cell *matHeaderCellDef> Symbol </th>
<td mat-cell *matCellDef="let element"> {{element.symbol}}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row
*matRowDef="let row;
columns: displayedColumns;"></tr>
</table>
</div>
<div fxFlex="45"></div>
</div>
After:
<div fxFlex fxLayout="row wrap">
<div fxFlex="5"></div>
<div fxFlex="50" class="mat-elevation-z8">
<table mat-table
#dataTable
fxFlex
[dataSource]="dataSource"
cdkDropList
(cdkDropListDropped)="dropTable($event)">
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef> Weight </th>
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="symbol">
<th mat-header-cell *matHeaderCellDef> Symbol </th>
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row
*matRowDef="let row;
columns: displayedColumns;"
cdkDrag
></tr>
<div *cdkDragPlaceholder></div>
</table>
</div>
<div fxFlex="45"></div>
</div>
Adding Drag and Drop
to src\app\app.component.ts
, before:
import { Component } from '@angular/core';
export interface PeriodicElement {
name: string;
weight: number;
symbol: string;
}
const ELEMENT_DATA: PeriodicElement[] = [
{name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
{name: 'Helium', weight: 4.0026, symbol: 'He'},
{name: 'Lithium', weight: 6.941, symbol: 'Li'},
{name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
{name: 'Boron', weight: 10.811, symbol: 'B'},
{name: 'Carbon', weight: 12.0107, symbol: 'C'},
{name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
{name: 'Oxygen', weight: 15.9994, symbol: 'O'},
{name: 'Fluorine', weight: 18.9984, symbol: 'F'},
{name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
displayedColumns: string[] = ['name', 'weight', 'symbol'];
dataSource = ELEMENT_DATA;
}
After:
import { Component, ViewChild } from '@angular/core';
import { MatTable } from '@angular/material/table';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
export interface PeriodicElement {
name: string;
weight: number;
symbol: string;
}
const ELEMENT_DATA: PeriodicElement[] = [
{name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
{name: 'Helium', weight: 4.0026, symbol: 'He'},
{name: 'Lithium', weight: 6.941, symbol: 'Li'},
{name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
{name: 'Boron', weight: 10.811, symbol: 'B'},
{name: 'Carbon', weight: 12.0107, symbol: 'C'},
{name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
{name: 'Oxygen', weight: 15.9994, symbol: 'O'},
{name: 'Fluorine', weight: 18.9984, symbol: 'F'},
{name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
@ViewChild('dataTable') table: MatTable<PeriodicElement>;
displayedColumns: string[] = ['name', 'weight', 'symbol'];
dataSource = ELEMENT_DATA;
dropTable(event: CdkDragDrop<PeriodicElement[]>): void {
moveItemInArray(this.dataSource, event.previousIndex, event.currentIndex);
this.table.renderRows();
}
}