Skip to content

Commit c8ae9fd

Browse files
crisbetojelbourn
authored andcommitted
docs(drag-drop): add docs and live examples (#12794)
Adds live examples and a readme for the CDK drag&drop.
1 parent e5e5b68 commit c8ae9fd

23 files changed

+616
-1
lines changed

src/cdk/drag-drop/drag-drop.md

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,118 @@
1-
# TODO
1+
The `@angular/cdk/drag-drop` module provides you with a way to easily and declaratively create
2+
drag-and-drop interfaces, with support for free dragging, sorting within a list, transferring items
3+
between lists, animations, touch devices, custom drag handles, previews, and placeholders,
4+
in addition to horizontal lists and locking along an axis.
5+
6+
### Getting started
7+
Start by importing `DragDropModule` into the `NgModule` where you want to use drag-and-drop
8+
features. You can now add the `cdkDrag` directive to elements to make them draggable. When
9+
outside of a `<cdk-drop>` element, draggable elements can be freely moved around the page.
10+
You can add `<cdk-drop>` elements to constrain where elements may be dropped.
11+
12+
<!-- example(cdk-drag-drop-overview) -->
13+
14+
### Reordering lists
15+
Adding `<cdk-drop>` around a set of `cdkDrag` elements groups the draggables into a
16+
reorderable collection. Items will automatically rearrange as an element moves. Note
17+
that this will *not* update your data model; you can listen to the `dropped` event to
18+
update the data model once the user finishes dragging.
19+
20+
<!-- example(cdk-drag-drop-sorting) -->
21+
22+
### Transferring items between lists
23+
The `<cdk-drop>` component supports transferring dragged items between connected drop zones.
24+
You can connect one or more `<cdk-drop>` instances together by setting the `connectedTo`
25+
property.
26+
27+
<!-- example(cdk-drag-drop-connected-sorting) -->
28+
29+
Note that `connectedTo` works both with a direct reference to another `<cdk-drop>`, or by
30+
referencing the `id` of another drop container:
31+
32+
```html
33+
<!-- This is valid -->
34+
<cdk-drop #listOne [connectedTo]="[listTwo]"></cdk-drop>
35+
<cdk-drop #listTwo [connectedTo]="[listOne]"></cdk-drop>
36+
37+
<!-- This is valid as well -->
38+
<cdk-drop id="list-one" [connectedTo]="['list-two']"></cdk-drop>
39+
<cdk-drop id="list-two" [connectedTo]="['list-one']"></cdk-drop>
40+
```
41+
42+
### Attaching data
43+
You can associate some arbitrary data with both `cdkDrag` and `<cdk-drop>` by setting
44+
`cdkDragData` or `data`, respectively. Events fired from both directives include this data,
45+
allowing you to easily identify the origin of the drag or drop interaction.
46+
47+
```html
48+
<cdk-drop [data]="list" *ngFor="let list of lists" (dropped)="drop($event)">
49+
<div cdkDrag [cdkDragData]="item" *ngFor="let item of list"></div>
50+
</cdk-drop>
51+
```
52+
53+
### Styling
54+
The `cdkDrag` and `<cdk-drop>` directive include only those styles strictly necessary for
55+
functionality. The application can then customize the elements by styling CSS classes added
56+
by the directives:
57+
58+
| Selector | Description |
59+
|---------------------|--------------------------------------------------------------------------|
60+
| `.cdk-drop` | Corresponds to the `<cdk-drop>` container. |
61+
| `.cdk-drag` | Corresponds to a `cdkDrag` instance. |
62+
| `.cdk-drag-preview` | This is the element that will be rendered next to the user's cursor as they're dragging an item in a sortable list. By default the element looks exactly like the element that is being dragged. |
63+
| `.cdk-drag-placeholder` | This is element that will be shown instead of the real element as it's being dragged inside a `<cdk-drop>`. By default this will look exactly like the element that is being sorted. |
64+
| `.cdk-drop-dragging` | A class that is added to `<cdk-drop>` while the user is dragging an item. |
65+
66+
### Animations
67+
The drag-and-drop module supports animations both while sorting an element inside a list, as well as
68+
animating it from the position that the user dropped it to its final place in the list. To set up
69+
your animations, you have to define a `transition` that targets the `transform` property. The
70+
following classes can be used for animations:
71+
72+
* `.cdk-drag` - If you add a `transition` to this class, it'll animate as the user is sorting
73+
through a list.
74+
* `.cdk-drag-animating` - This class is added to a `cdkDrag` when the user has stopped dragging.
75+
If you add a `transition` to it, the CDK will animate the element from its drop position to
76+
the final position inside the `<cdk-drop>` container.
77+
78+
Example animations:
79+
80+
```css
81+
/* Animate items as they're being sorted. */
82+
.cdk-drop-dragging .cdk-drag {
83+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
84+
}
85+
86+
/* Animate an item that has been dropped. */
87+
.cdk-drag-animating {
88+
transition: transform 300ms cubic-bezier(0, 0, 0.2, 1);
89+
}
90+
```
91+
92+
### Customizing the drag area using a handle
93+
By default, the user can drag the entire `cdkDrag` element to move it around. If you want to
94+
restrict the user to only be able to do so using a handle element, you can do it by adding the
95+
`cdkDragHandle` directive to an element inside of `cdkDrag`. Note that you can have as many
96+
`cdkDragHandle` elements as you want:
97+
98+
<!-- example(cdk-drag-drop-handle) -->
99+
100+
### Customizing the drag preview
101+
When a `cdkDrag` element is picked up, it will create a preview element visible while dragging.
102+
By default, this will be a clone of the original element positioned next to the user's cursor.
103+
This preview can be customized, though, by providing a custom template via `*cdkDragPreview`:
104+
105+
<!-- example(cdk-drag-drop-custom-preview) -->
106+
107+
### List orientation
108+
The `cdk-drop` component assumes that lists are vertical by default. This can be
109+
changed by setting the `orientation` property to `"horizontal".
110+
111+
<!-- example(cdk-drag-drop-horizontal-sorting) -->
112+
113+
### Restricting movement along an axis
114+
By default, `cdkDrag` allows free movement in all directions. To restrict dragging to a
115+
specific axis, you can set `cdkDragLockAxis` on `cdkDrag` or `lockAxis` on `<cdk-drop>`
116+
to either `"x"` or `"y"`.
117+
118+
<!-- example(cdk-drag-drop-axis-lock) -->
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
.box {
2+
width: 200px;
3+
height: 200px;
4+
border: solid 1px #ccc;
5+
cursor: move;
6+
display: inline-flex;
7+
justify-content: center;
8+
align-items: center;
9+
background: #fff;
10+
border-radius: 4px;
11+
margin-right: 25px;
12+
transition: box-shadow 200ms cubic-bezier(0, 0, 0.2, 1);
13+
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2),
14+
0 2px 2px 0 rgba(0, 0, 0, 0.14),
15+
0 1px 5px 0 rgba(0, 0, 0, 0.12);
16+
}
17+
18+
.box:active {
19+
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
20+
0 8px 10px 1px rgba(0, 0, 0, 0.14),
21+
0 3px 14px 2px rgba(0, 0, 0, 0.12);
22+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<div class="box" cdkDragLockAxis="y" cdkDrag>
2+
I can only be dragged up/down
3+
</div>
4+
5+
<div class="box" cdkDragLockAxis="x" cdkDrag>
6+
I can only be dragged left/right
7+
</div>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {Component} from '@angular/core';
2+
3+
/**
4+
* @title Drag&Drop position locking
5+
*/
6+
@Component({
7+
selector: 'cdk-drag-drop-axis-lock-example',
8+
templateUrl: 'cdk-drag-drop-axis-lock-example.html',
9+
styleUrls: ['cdk-drag-drop-axis-lock-example.css'],
10+
})
11+
export class CdkDragDropAxisLockExample {}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
.container {
2+
width: 400px;
3+
max-width: 100%;
4+
margin: 0 25px 25px 0;
5+
display: inline-block;
6+
vertical-align: top;
7+
}
8+
9+
.list {
10+
border: solid 1px #ccc;
11+
min-height: 60px;
12+
background: white;
13+
border-radius: 4px;
14+
overflow: hidden;
15+
display: block;
16+
}
17+
18+
.box {
19+
padding: 20px 10px;
20+
border-bottom: solid 1px #ccc;
21+
display: flex;
22+
flex-direction: row;
23+
align-items: center;
24+
justify-content: space-between;
25+
box-sizing: border-box;
26+
cursor: move;
27+
background: white;
28+
font-size: 14px;
29+
}
30+
31+
.cdk-drag-preview {
32+
box-sizing: border-box;
33+
border-radius: 4px;
34+
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
35+
0 8px 10px 1px rgba(0, 0, 0, 0.14),
36+
0 3px 14px 2px rgba(0, 0, 0, 0.12);
37+
}
38+
39+
.cdk-drag-placeholder {
40+
opacity: 0;
41+
}
42+
43+
.cdk-drag-animating {
44+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
45+
}
46+
47+
.box:last-child {
48+
border: none;
49+
}
50+
51+
.list.cdk-drop-dragging .box:not(.cdk-drag-placeholder) {
52+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
53+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<div class="container">
2+
<h2>To do</h2>
3+
4+
<cdk-drop #todoList [data]="todo" [connectedTo]="[doneList]" class="list" (dropped)="drop($event)">
5+
<div class="box" *ngFor="let item of todo" cdkDrag>{{item}}</div>
6+
</cdk-drop>
7+
</div>
8+
9+
<div class="container">
10+
<h2>Done</h2>
11+
12+
<cdk-drop #doneList [data]="done" [connectedTo]="[todoList]" class="list" (dropped)="drop($event)">
13+
<div class="box" *ngFor="let item of done" cdkDrag>{{item}}</div>
14+
</cdk-drop>
15+
</div>
16+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import {Component} from '@angular/core';
2+
import {CdkDragDrop, moveItemInArray, transferArrayItem} from '@angular/cdk/drag-drop';
3+
4+
/**
5+
* @title Drag&Drop connected sorting
6+
*/
7+
@Component({
8+
selector: 'cdk-drag-drop-connected-sorting-example',
9+
templateUrl: 'cdk-drag-drop-connected-sorting-example.html',
10+
styleUrls: ['cdk-drag-drop-connected-sorting-example.css'],
11+
})
12+
export class CdkDragDropConnectedSortingExample {
13+
todo = [
14+
'Get to work',
15+
'Pick up groceries',
16+
'Go home',
17+
'Fall asleep'
18+
];
19+
20+
done = [
21+
'Get up',
22+
'Brush teeth',
23+
'Take a shower',
24+
'Check e-mail',
25+
'Walk dog'
26+
];
27+
28+
drop(event: CdkDragDrop<string[]>) {
29+
if (event.previousContainer === event.container) {
30+
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
31+
} else {
32+
transferArrayItem(event.previousContainer.data,
33+
event.container.data,
34+
event.previousIndex,
35+
event.currentIndex);
36+
}
37+
}
38+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
.list {
2+
width: 500px;
3+
max-width: 100%;
4+
border: solid 1px #ccc;
5+
min-height: 60px;
6+
display: block;
7+
background: white;
8+
border-radius: 4px;
9+
overflow: hidden;
10+
}
11+
12+
.box {
13+
padding: 20px 10px;
14+
border-bottom: solid 1px #ccc;
15+
display: flex;
16+
flex-direction: row;
17+
align-items: center;
18+
justify-content: space-between;
19+
box-sizing: border-box;
20+
cursor: move;
21+
background: white;
22+
font-size: 14px;
23+
}
24+
25+
.cdk-drag-preview {
26+
box-sizing: border-box;
27+
border-radius: 4px;
28+
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
29+
0 8px 10px 1px rgba(0, 0, 0, 0.14),
30+
0 3px 14px 2px rgba(0, 0, 0, 0.12);
31+
}
32+
33+
.cdk-drag-placeholder {
34+
opacity: 0;
35+
}
36+
37+
.cdk-drag-animating {
38+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
39+
}
40+
41+
.box:last-child {
42+
border: none;
43+
}
44+
45+
.list.cdk-drop-dragging .box:not(.cdk-drag-placeholder) {
46+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
47+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<cdk-drop class="list" (dropped)="drop($event)">
2+
<div class="box" *ngFor="let movie of movies" cdkDrag>
3+
{{movie.title}}
4+
<img *cdkDragPreview [src]="movie.poster" [alt]="movie.title">
5+
</div>
6+
</cdk-drop>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import {Component} from '@angular/core';
2+
import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop';
3+
4+
/**
5+
* @title Drag&Drop custom preview
6+
*/
7+
@Component({
8+
selector: 'cdk-drag-drop-custom-preview-example',
9+
templateUrl: 'cdk-drag-drop-custom-preview-example.html',
10+
styleUrls: ['cdk-drag-drop-custom-preview-example.css'],
11+
})
12+
export class CdkDragDropCustomPreviewExample {
13+
// tslint:disable:max-line-length
14+
movies = [
15+
{
16+
title: 'Episode I - The Phantom Menace',
17+
poster: 'https://upload.wikimedia.org/wikipedia/en/4/40/Star_Wars_Phantom_Menace_poster.jpg'
18+
},
19+
{
20+
title: 'Episode II - Attack of the Clones',
21+
poster: 'https://upload.wikimedia.org/wikipedia/en/3/32/Star_Wars_-_Episode_II_Attack_of_the_Clones_%28movie_poster%29.jpg'
22+
},
23+
{
24+
title: 'Episode III - Revenge of the Sith',
25+
poster: 'https://upload.wikimedia.org/wikipedia/en/9/93/Star_Wars_Episode_III_Revenge_of_the_Sith_poster.jpg'
26+
},
27+
{
28+
title: 'Episode IV - A New Hope',
29+
poster: 'https://upload.wikimedia.org/wikipedia/en/8/87/StarWarsMoviePoster1977.jpg'
30+
},
31+
{
32+
title: 'Episode V - The Empire Strikes Back',
33+
poster: 'https://upload.wikimedia.org/wikipedia/en/3/3c/SW_-_Empire_Strikes_Back.jpg'
34+
},
35+
{
36+
title: 'Episode VI - Return of the Jedi',
37+
poster: 'https://upload.wikimedia.org/wikipedia/en/b/b2/ReturnOfTheJediPoster1983.jpg'
38+
},
39+
{
40+
title: 'Episode VII - The Force Awakens',
41+
poster: 'https://upload.wikimedia.org/wikipedia/en/a/a2/Star_Wars_The_Force_Awakens_Theatrical_Poster.jpg'
42+
},
43+
{
44+
title: 'Episode VIII - The Last Jedi',
45+
poster: 'https://upload.wikimedia.org/wikipedia/en/7/7f/Star_Wars_The_Last_Jedi.jpg'
46+
}
47+
];
48+
// tslint:enable:max-line-length
49+
50+
drop(event: CdkDragDrop<{title: string, poster: string}[]>) {
51+
moveItemInArray(this.movies, event.previousIndex, event.currentIndex);
52+
}
53+
}

0 commit comments

Comments
 (0)