Skip to content

Commit f99a068

Browse files
committed
docs(drag-drop): add docs and live examples
Adds live examples and a readme for the CDK drag&drop.
1 parent dad0ed0 commit f99a068

23 files changed

+625
-1
lines changed

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

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,127 @@
1-
# TODO
1+
The `@angular/cdk/drag-drop` module provides you with a way to easily and declaratively create
2+
drag&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+
To get started, you have to include the `DragDropModule` in your app's imports and add the
8+
`cdkDrag` directive to the element that you want to be draggable. When a `cdkDrag` element is
9+
outside of a `cdk-drop` element, it's in "free dragging" mode, which means that the user will be
10+
able to drag it freely around the page.
11+
12+
<!-- example(cdk-drag-drop-overview) -->
13+
14+
### Sorting
15+
If you want to take your UI a step further and allow the user to re-arrange a list of data using
16+
drag&drop, you can do so using the `cdk-drop` directive. When a `cdk-drop` is added around some
17+
`cdkDrag` elements, they'll become grouped in a list and the CDK will automatically sort them
18+
as the user is dragging. Note that the CDK won't change the data for you, which means that you'll
19+
have to listen for the `dropped` event and re-arrange the date yourself once the user is done
20+
dragging. There are some provided utilities like the `moveItemInArray` and `transferArrayItem`
21+
functions that make it easier to manipulate your data.
22+
23+
<!-- example(cdk-drag-drop-sorting) -->
24+
25+
### Sorting between lists
26+
The drag&drop module has the ability to transfer items between `cdk-drop` lists. You can connect
27+
two lists using the `connectedTo` input on the `cdk-drop` component, which tells the CDK the items
28+
from which lists can be dropped into the current list.
29+
30+
<!-- example(cdk-drag-drop-connected-sorting) -->
31+
32+
Note that `connectedTo` works both with a direct reference to another `cdk-drop`, or by
33+
referencing the `id` of another drop container:
34+
35+
```html
36+
<!-- This is valid -->
37+
<cdk-drop #listOne [connectedTo]="[listTwo]"></cdk-drop>
38+
<cdk-drop #listTwo [connectedTo]="[listOne]"></cdk-drop>
39+
40+
<!-- This is valid as well -->
41+
<cdk-drop id="list-one" [connectedTo]="['list-two']"></cdk-drop>
42+
<cdk-drop id="list-two" [connectedTo]="['list-one']"></cdk-drop>
43+
```
44+
45+
### Attaching data
46+
When dealing with connected sorting lists inside an `ngFor` that all reuse the same `dropped`
47+
callback, it can be difficult to know what list was being sorted or which item was dropped. To
48+
make this easier, you can associate data both with `cdk-drop` and `cdkDrag` through the
49+
`data` and `cdkDragData` inputs respectively. This data will be passed along to all of the
50+
emitted events.
51+
52+
```html
53+
<cdk-drop [data]="list" *ngFor="let list of lists" (dropped)="drop($event)">
54+
<div cdkDrag [cdkDragData]="item" *ngFor="let item of list"></div>
55+
</cdk-drop>
56+
```
57+
58+
### Styling
59+
By default, the CDK drag&drop comes with a minimal set of structural styles, which means that it's
60+
up to you to define what the components should look like. You can target the following selectors
61+
in order to customize the component's appearance:
62+
63+
* `.cdk-drop` - Corresponds to the `<cdk-drop>` container.
64+
* `.cdk-drag` - Corresponds to a `cdkDrag` instance.
65+
* `.cdk-drag-preview` - This is the element that will be rendered next to the user's
66+
cursor as they're dragging an item in a sortable list. By default the element looks exactly like
67+
the element that is being dragged.
68+
* `.cdk-drag-placeholder` - This is element that will be shown instead of the real element as it's
69+
being dragged inside a `cdk-drop`. By default this will look exactly like the element that is
70+
being sorted.
71+
* `.cdk-drop-dragging` - A class that is added to `cdk-drop` while the user is dragging an item.
72+
73+
### Animations
74+
The drag&drop module supports animations both while sorting an element inside a list, as well as
75+
animating it from the position that the user dropped it to its final place in the list. To set up
76+
your animations, you have to define a `transition` that targets the `transform` property. The
77+
following classes can be used for animations:
78+
79+
* `.cdk-drag` - If you add a `transition` to this class, it'll animate as the user is sorting
80+
through a list.
81+
* `.cdk-drag-animating` - This class is added to a `cdkDrag` when the user has stopped dragging.
82+
If you add a `transition` to it, the CDK will animate the element from its drop position to
83+
the final position inside the `cdk-drop` container.
84+
85+
Example animations:
86+
87+
```css
88+
/* Animate items as they're being sorted. */
89+
.cdk-drop-dragging .cdk-drag {
90+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
91+
}
92+
93+
/* Animate an item that has been dropped. */
94+
.cdk-drag-animating {
95+
transition: transform 300ms cubic-bezier(0, 0, 0.2, 1);
96+
}
97+
```
98+
99+
### Customizing the drag area using a handle
100+
By default, the user can drag the entire `cdkDrag` element to move it around. If you want to
101+
restrict the user to only be able to do so using a handle element, you can do it by adding the
102+
`cdkDragHandle` directive to an element inside of `cdkDrag`. Note that you can have as many
103+
`cdkDragHandle` elements as you want:
104+
105+
<!-- example(cdk-drag-drop-handle) -->
106+
107+
### Customizing the preview element
108+
By default, when the user starts dragging an item inside a sortable list, the CDK will create a
109+
preview element that looks exactly like the element that is being dragged, and will position it
110+
next to the user's cursor. If you want to customize how the preview looks, you can either target
111+
the `.cdk-drag-preview` using CSS, or you can provide a completely new template using the
112+
`*cdkDragPreview` directive:
113+
114+
<!-- example(cdk-drag-drop-custom-preview) -->
115+
116+
### List orientation
117+
The `cdk-drop` component defaults to sorting lists vertically, however you can make a list that is
118+
sorted horizontally by setting the `orientation` input to `horizontal`:
119+
120+
<!-- example(cdk-drag-drop-horizontal-sorting) -->
121+
122+
### Restricting movement along an axis
123+
By default, the CDK allows the user to move the drag preview around freely in both the X and Y axis,
124+
however you can restrict movement along one of the using the `cdkDragLockAxis` directive. This
125+
directive is also available on the `cdk-drop` component as `lockAxis`.
126+
127+
<!-- 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)