Component Dev Kit (CDK), bileşen oluşturmak için bir davranış ilkeleri setidir. Sürükle ve bırak direktiflerini kullanmak için önce npm'den @angular/cdk yükleyin. Bunu Angular CLI kullanarak terminalinizden yapabilirsiniz:
cdkDrag direktifini ekleyerek herhangi bir öğeyi sürüklenebilir yapabilirsiniz. Varsayılan olarak, tüm sürüklenebilir öğeler serbest sürüklemeyi destekler.
app.html
<div class="example-box" cdkDrag>Drag me around</div>
app.ts
import {CdkDrag} from '@angular/cdk/drag-drop';import {Component} from '@angular/core';/** * @title Basic Drag&Drop */@Component({ selector: 'cdk-drag-drop-overview-example', templateUrl: 'app.html', styleUrl: 'app.css', imports: [CdkDrag],})export class CdkDragDropOverviewExample {}
Sürüklenebilir öğeleri yeniden sıralanabilir bir koleksiyona gruplamak için bir üst öğeye cdkDropList direktifini ekleyin. Bu, sürüklenebilir öğelerin nereye bırakılabileceğini tanımlar. Bırakma listesi grubundaki sürüklenebilir öğeler, bir öğe hareket ettiğinde otomatik olarak yeniden düzenlenir.
Sürükle ve bırak direktifleri veri modelinizi güncellemez. Veri modelini güncellemek için cdkDropListDropped olayını dinleyin (kullanıcı sürüklemeyi bitirdiğinde) ve veri modelini manuel olarak güncelleyin.
app.html
<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)"> @for (movie of movies; track movie) { <div class="example-box" cdkDrag>{{ movie }}</div> }</div>
app.ts
import {CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray} from '@angular/cdk/drag-drop';import {Component} from '@angular/core';/** * @title Drag&Drop sorting */@Component({ selector: 'cdk-drag-drop-sorting-example', templateUrl: 'app.html', styleUrl: 'app.css', imports: [CdkDropList, CdkDrag],})export class CdkDragDropSortingExample { movies = [ 'Episode I - The Phantom Menace', 'Episode II - Attack of the Clones', 'Episode III - Revenge of the Sith', 'Episode IV - A New Hope', 'Episode V - The Empire Strikes Back', 'Episode VI - Return of the Jedi', 'Episode VII - The Force Awakens', 'Episode VIII - The Last Jedi', 'Episode IX - The Rise of Skywalker', ]; drop(event:CdkDragDrop<string[]>) {moveItemInArray(this.movies, event.previousIndex, event.currentIndex); }}
cdkDropList direktifi, bağlı bırakma listeleri arasında sürüklenebilir öğelerin aktarılmasını destekler. Bir veya daha fazla cdkDropList örneğini birbirine bağlamanın iki yolu vardır:
cdkDropListConnectedTo özelliğini başka bir bırakma listesine ayarlayın.
Öğeleri cdkDropListGroup niteliğine sahip bir öğe ile sarın.
cdkDropListConnectedTo direktifi hem başka bir cdkDropList'e doğrudan referans hem de başka bir bırakma kapsayıcısının kimliğine referans ile çalışır.
<!-- Bu geçerlidir --><div cdkDropList #listOne="cdkDropList" [cdkDropListConnectedTo]="[listTwo]"></div><div cdkDropList #listTwo="cdkDropList" [cdkDropListConnectedTo]="[listOne]"></div><!-- Bu da geçerlidir --><div cdkDropList id="list-one" [cdkDropListConnectedTo]="['list-two']"></div><div cdkDropList id="list-two" [cdkDropListConnectedTo]="['list-one']"></div>
Bilinmeyen sayıda bağlı bırakma listeniz varsa bağlantıyı otomatik olarak kurmak için cdkDropListGroup direktifini kullanın. Bir grup altına eklenen herhangi bir yeni cdkDropList otomatik olarak diğer tüm listelere bağlanır.
<div cdkDropListGroup> <!-- Buradaki tüm listeler birbirine bağlanacaktır. --> @for (list of lists; track list) { <div cdkDropList></div> }</div>
Varsayılan olarak, bir kullanıcı cdkDrag öğelerini bir kapsayıcıdan bağlı başka bir kapsayıcıya taşıyabilir. Hangi öğelerin bir kapsayıcıya bırakılabileceği üzerinde daha ayrıntılı kontrol için cdkDropListEnterPredicate kullanın. Angular, sürüklenebilir bir öğe yeni bir kapsayıcıya her girdiğinde yüklemi çağırır. Yüklemin true veya false döndürmesine bağlı olarak, öğeye yeni kapsayıcıya girilmesine izin verilebilir veya verilmeyebilir.
import {CdkDrag,CdkDragDrop,CdkDropList,moveItemInArray,transferArrayItem,} from '@angular/cdk/drag-drop';import {Component} from '@angular/core';/** * @title Drag&Drop enter predicate */@Component({ selector: 'cdk-drag-drop-enter-predicate-example', templateUrl: 'app.html', styleUrl: 'app.css', imports: [CdkDropList, CdkDrag],})export class CdkDragDropEnterPredicateExample { all = [1, 2, 3, 4, 5, 6, 7, 8, 9]; even = [10]; drop(event:CdkDragDrop<number[]>) { if (event.previousContainer === event.container) {moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); } else {transferArrayItem( event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex, ); } } /** Predicate function that only allows even numbers to be dropped into a list. */ evenPredicate(item:CdkDrag<number>) { return item.data % 2 === 0; } /** Predicate function that doesn't allow items to be dropped into a list. */ noReturnPredicate() { return false; }}
Sırasıyla cdkDragData veya cdkDropListData ayarlayarak hem cdkDrag hem de cdkDropList ile rastgele veriler ilişkilendirebilirsiniz. Her iki direktiften tetiklenen olaylara bağlanabilir ve bu veriler dahil olacaktır, böylece sürükleme veya bırakma etkileşiminin kaynağını kolayca tanımlayabilirsiniz.
Varsayılan olarak, kullanıcı onu hareket ettirmek için tüm cdkDrag öğesini sürükleyebilir. Kullanıcıyı bunu yalnızca bir tutamaç öğesi kullanarak yapabilmeye kısıtlamak için cdkDrag içindeki bir öğeye cdkDragHandle direktifini ekleyin. İstediğiniz kadar cdkDragHandle öğesine sahip olabilirsiniz.
app.html
<div class="example-box" cdkDrag> I can only be dragged using the handle <div class="example-handle" cdkDragHandle> <svg width="24px" fill="currentColor" viewBox="0 0 24 24"> <path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z" ></path> <path d="M0 0h24v24H0z" fill="none"></path> </svg> </div></div>
app.ts
import {CdkDrag, CdkDragHandle} from '@angular/cdk/drag-drop';import {Component} from '@angular/core';/** * @title Drag&Drop with a handle */@Component({ selector: 'cdk-drag-drop-handle-example', templateUrl: 'app.html', styleUrl: 'app.css', imports: [CdkDrag, CdkDragHandle],})export class CdkDragDropHandleExample {}
Bir cdkDrag öğesi sürüklenirken bir önizleme öğesi görünür hale gelir. Varsayılan olarak önizleme, kullanıcının imlecinin yanında konumlandırılmış orijinal öğenin bir klonudur.
Önizlemeyi özelleştirmek için *cdkDragPreview aracılığıyla özel bir şablon sağlayın. Özel önizleme, öğenin içeriği hakkında varsayımlar yapılmadığından orijinal sürüklenen öğenin boyutuyla eşleşmez. Öğe boyutuyla eşleştirmek için matchSize girişine true geçirin.
Klonlanan öğe, sayfada aynı kimliğe sahip birden fazla öğe olmasını önlemek için id niteliğini kaldırır. Bu, o kimliği hedefleyen herhangi bir CSS'in uygulanmamasına neden olur.
Varsayılan olarak, Angular konumlandırma ve taşma ile ilgili sorunları önlemek için cdkDrag önizlemesini sayfanın <body> öğesine ekler. Bazı durumlarda bu istenmeyebilir çünkü önizleme devralınan stilleri almayacaktır.
Angular'ın önizlemeyi nereye eklediğini cdkDrag üzerindeki cdkDragPreviewContainer girişini kullanarak değiştirebilirsiniz. Olası değerler şunlardır:
Value
Description
Advantages
Disadvantages
global
Varsayılan değer. Angular önizlemeyi veya en yakın shadow root'a ekler.
Önizleme z-index veya overflow: hidden tarafından etkilenmez. Ayrıca :nth-child seçicilerini ve flex düzenlerini etkilemez.
Devralınan stilleri almaz.
parent
Angular önizlemeyi sürüklenen öğenin üst öğesi içine ekler.
Önizleme sürüklenen öğe ile aynı stilleri devralır.
Önizleme overflow: hidden tarafından kırpılabilir veya z-index nedeniyle diğer öğelerin altına yerleştirilebilir. Ayrıca :nth-child seçicilerini ve bazı flex düzenlerini etkileyebilir.
Önizleme overflow: hidden tarafından kırpılabilir veya z-index nedeniyle diğer öğelerin altına yerleştirilebilir. Ayrıca :nth-child seçicilerini ve bazı flex düzenlerini etkileyebilir.
Bir cdkDrag öğesi sürüklenirken, direktif öğenin bırakıldığında nereye yerleştirileceğini gösteren bir yer tutucu öğe oluşturur. Varsayılan olarak, yer tutucu sürüklenen öğenin bir klonudur. *cdkDragPlaceholder direktifini kullanarak yer tutucuyu özel biriyle değiştirebilirsiniz:
import {CdkDrag,CdkDragDrop,CdkDragPlaceholder,CdkDropList,moveItemInArray,} from '@angular/cdk/drag-drop';import {Component} from '@angular/core';/** * @title Drag&Drop custom placeholder */@Component({ selector: 'cdk-drag-drop-custom-placeholder-example', templateUrl: 'app.html', styleUrl: 'app.css', imports: [CdkDropList, CdkDrag, CdkDragPlaceholder],})export class CdkDragDropCustomPlaceholderExample { movies = [ 'Episode I - The Phantom Menace', 'Episode II - Attack of the Clones', 'Episode III - Revenge of the Sith', 'Episode IV - A New Hope', 'Episode V - The Empire Strikes Back', 'Episode VI - Return of the Jedi', 'Episode VII - The Force Awakens', 'Episode VIII - The Last Jedi', 'Episode IX - The Rise of Skywalker', ]; drop(event:CdkDragDrop<string[]>) {moveItemInArray(this.movies, event.previousIndex, event.currentIndex); }}
Sürüklenebilir yapmak istediğiniz ancak doğrudan erişiminiz olmayan bir öğe varsa cdkDragRootElement niteliğini ayarlayın.
Nitelik bir seçici kabul eder ve seçiciyle eşleşen bir öğe bulana kadar DOM'u yukarı doğru arar. Bir öğe bulunursa sürüklenebilir hale gelir. Bu, bir diyaloğu sürüklenebilir yapmak gibi durumlar için kullanışlıdır.
app.html
<button type="button" (click)="openDialog()">Open a draggable dialog</button><ng-template> <div class="example-dialog-content" cdkDrag cdkDragRootElement=".cdk-overlay-pane"> Drag the dialog around! </div></ng-template>
app.ts
import {CdkDrag} from '@angular/cdk/drag-drop';import {Overlay, OverlayRef} from '@angular/cdk/overlay';import {TemplatePortal} from '@angular/cdk/portal';import {AfterViewInit,Component,OnDestroy,TemplateRef,ViewContainerRef, inject,viewChild,} from '@angular/core';/** * @title Drag&Drop with alternate root element */@Component({ selector: 'cdk-drag-drop-root-element-example', templateUrl: 'app.html', styleUrl: 'app.css', imports: [CdkDrag],})export class CdkDragDropRootElementExample implementsAfterViewInit, OnDestroy { private _overlay = inject(Overlay); private _viewContainerRef = inject(ViewContainerRef); private _dialogTemplate =viewChild.required(TemplateRef); private _overlayRef!: OverlayRef; private _portal!: TemplatePortal; ngAfterViewInit() { this._portal = new TemplatePortal(this._dialogTemplate(), this._viewContainerRef); this._overlayRef = this._overlay.create({ positionStrategy: this._overlay.position().global().centerHorizontally().centerVertically(), hasBackdrop: true, }); this._overlayRef.backdropClick().subscribe(() => this._overlayRef.detach()); } ngOnDestroy() { this._overlayRef.dispose(); } openDialog() { this._overlayRef.attach(this._portal); }}
Varsayılan olarak, cdkDropList içinde olmayan cdkDrag öğeleri yalnızca kullanıcı öğeyi manuel olarak hareket ettirdiğinde normal DOM konumlarından hareket eder. Öğenin konumunu açıkça ayarlamak için cdkDragFreeDragPosition girişini kullanın. Bunun yaygın bir kullanım durumu, kullanıcı uzaklaştıktan ve geri döndükten sonra sürüklenebilir bir öğenin konumunu geri yüklemektir.
app.html
<p> <button type="button" (click)="changePosition()">Change element position</button></p><div class="example-box" cdkDrag [cdkDragFreeDragPosition]="dragPosition">Drag me around</div>
app.ts
import {CdkDrag} from '@angular/cdk/drag-drop';import {Component} from '@angular/core';/** * @title Programmatically setting the free drag position */@Component({ selector: 'cdk-drag-drop-free-drag-position-example', templateUrl: 'app.html', styleUrl: 'app.css', imports: [CdkDrag],})export class CdkDragDropFreeDragPositionExample { dragPosition = {x: 0, y: 0}; changePosition() { this.dragPosition = {x: this.dragPosition.x + 50, y: this.dragPosition.y + 50}; }}
Kullanıcının bir cdkDrag öğesini başka bir öğenin dışına sürükleyememesini sağlamak için cdkDragBoundary niteliğine bir CSS seçicisi geçirin. Bu nitelik bir seçici kabul eder ve eşleşen bir öğe bulana kadar DOM'u yukarı doğru arar. Bir eşleşme bulunursa, öğe sürüklenebilir öğenin cdkDragBoundary dışına sürüklenemeyeceği sınır haline gelir. cdkDragBoundary, cdkDrag bir cdkDropList içine yerleştirildiğinde de kullanılabilir.
app.html
<div class="example-boundary"> <div class="example-box" cdkDragBoundary=".example-boundary" cdkDrag> I can only be dragged within the dotted container </div></div>
app.ts
import {CdkDrag} from '@angular/cdk/drag-drop';import {Component} from '@angular/core';/** * @title Drag&Drop boundary */@Component({ selector: 'cdk-drag-drop-boundary-example', templateUrl: 'app.html', styleUrl: 'app.css', imports: [CdkDrag],})export class CdkDragDropBoundaryExample {}
Varsayılan olarak, cdkDrag tüm yönlerde serbest harekete izin verir. Sürüklemeyi belirli bir eksene kısıtlamak için cdkDrag üzerinde cdkDragLockAxis'i "x" veya "y" olarak ayarlayın. cdkDropList içindeki birden fazla sürüklenebilir öğe için sürüklemeyi kısıtlamak amacıyla bunun yerine cdkDropList üzerinde cdkDropListLockAxis ayarlayın.
app.html
<div class="example-box" cdkDragLockAxis="y" cdkDrag>I can only be dragged up/down</div><div class="example-box" cdkDragLockAxis="x" cdkDrag>I can only be dragged left/right</div>
app.ts
import {CdkDrag} from '@angular/cdk/drag-drop';import {Component} from '@angular/core';/** * @title Drag&Drop position locking */@Component({ selector: 'cdk-drag-drop-axis-lock-example', templateUrl: 'app.html', styleUrl: 'app.css', imports: [CdkDrag],})export class CdkDragDropAxisLockExample {}
Varsayılan olarak kullanıcı bir cdkDrag öğesine işaretçisini bastığında sürükleme dizisi başlar. Bu davranış, dokunmatik cihazlarda tam ekran sürüklenebilir öğeler gibi kullanıcının sayfada kaydırma yaparken yanlışlıkla sürükleme olayı tetikleyebileceği durumlarda istenmeyebilir.
cdkDragStartDelay girişini kullanarak sürükleme dizisini geciktirebilirsiniz. Giriş, öğeyi sürüklemeden önce kullanıcının belirtilen milisaniye sayısı kadar işaretçisini basılı tutmasını bekler.
app.html
<div class="example-box" cdkDrag [cdkDragStartDelay]="1000">Dragging starts after one second</div>
app.ts
import {CdkDrag} from '@angular/cdk/drag-drop';import {Component} from '@angular/core';/** * @title Delay dragging */@Component({ selector: 'cdk-drag-drop-delay-example', templateUrl: 'app.html', styleUrl: 'app.css', imports: [CdkDrag],})export class CdkDragDropDelayExample {}
Belirli bir sürükleme öğesi için sürüklemeyi devre dışı bırakmak istiyorsanız, cdkDrag öğesinde cdkDragDisabled girişini true veya false olarak ayarlayın. cdkDropList üzerindeki cdkDropListDisabled girişini kullanarak tüm bir listeyi devre dışı bırakabilirsiniz. cdkDragHandle üzerindeki cdkDragHandleDisabled aracılığıyla belirli bir tutamacı devre dışı bırakmak da mümkündür.
Varsayılan olarak, cdkDropList direktifi listelerin dikey olduğunu varsayar. Bu, cdkDropListOrientation özelliğini horizontal olarak ayarlayarak değiştirilebilir.
Varsayılan olarak, cdkDropList sürüklenebilir öğeleri CSS dönüşümü kullanarak hareket ettirerek sıralar. Bu, sıralama işleminin animasyonlu olmasını sağlayarak daha iyi bir kullanıcı deneyimi sunar. Ancak bu, bırakma listesinin yalnızca bir yönde çalışması dezavantajını da beraberinde getirir: dikey veya yatay.
Yeni satırlara sarılması gereken sıralanabilir bir listeniz varsa, cdkDropListOrientation niteliğini mixed olarak ayarlayabilirsiniz. Bu, listenin öğeleri DOM'da hareket ettirmeyi içeren farklı bir sıralama stratejisi kullanmasına neden olur. Ancak liste artık sıralama eylemini animasyonlandıramaz.
Varsayılan olarak, cdkDrag öğeleri bir cdkDropList içinde herhangi bir konuma sıralanır. Bu davranışı değiştirmek için bir fonksiyon alan cdkDropListSortPredicate niteliğini ayarlayın. Yüklem fonksiyonu, sürüklenebilir bir öğe bırakma listesi içinde yeni bir dizine taşınmak üzereyken çağrılır. Yüklem true döndürürse, öğe yeni dizine taşınır, aksi takdirde mevcut konumunu korur.
app.html
<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)" [cdkDropListSortPredicate]="sortPredicate"> @for (number of numbers; track number) { <div class="example-box" [cdkDragData]="number" cdkDrag>{{ number }}</div> }</div>
app.ts
import {CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray} from '@angular/cdk/drag-drop';import {Component} from '@angular/core';/** * @title Drag&Drop sort predicate */@Component({ selector: 'cdk-drag-drop-sort-predicate-example', templateUrl: 'app.html', styleUrl: 'app.css', imports: [CdkDropList, CdkDrag],})export class CdkDragDropSortPredicateExample { numbers = [1, 2, 3, 4, 5, 6, 7, 8]; drop(event:CdkDragDrop<unknown>) {moveItemInArray(this.numbers, event.previousIndex, event.currentIndex); } /** * Predicate function that only allows even numbers to be * sorted into even indices and odd numbers at odd indices. */ sortPredicate(index: number, item:CdkDrag<number>) { return (index + 1) % 2 === item.data % 2; }}
Sürüklenebilir öğelerin bir cdkDropList'ten diğer bağlı bir listeye sürüklenebildiği ancak kullanıcının bunları kaynak listede sıralamaması gereken durumlar vardır. Bu durumlar için cdkDropList'teki sürüklenebilir öğelerin sıralanmasını engellemek amacıyla cdkDropListSortingDisabled niteliğini ekleyin. Bu, sürüklenen öğe yeni geçerli bir konuma sürüklenmezse kaynak listedeki ilk konumunu korur.
Varsayılan olarak, bir öğe bir listeden diğerine sürüklendiğinde, orijinal listesinden taşınır. Ancak, orijinal öğeyi kaynak listesinde bırakarak öğeyi kopyalamak için direktifleri yapılandırabilirsiniz.
Kopyalamayı etkinleştirmek için cdkDropListHasAnchor girişini ayarlayabilirsiniz. Bu, cdkDropList'e orijinal kapsayıcıda kalan ve öğeyle birlikte hareket etmeyen bir "çapa" öğesi oluşturmasını söyler. Kullanıcı öğeyi orijinal kapsayıcıya geri taşırsa, çapa otomatik olarak kaldırılır. Çapa öğesi .cdk-drag-anchor CSS sınıfı hedef alınarak stillenebilir.
cdkDropListHasAnchor'ı cdkDropListSortingDisabled ile birleştirmek, kullanıcının kaynak listeyi yeniden sıralayamadan öğeleri kopyalayabileceği bir liste oluşturmayı mümkün kılar (örneğin bir ürün listesi ve bir alışveriş sepeti).
Hem cdkDrag hem de cdkDropList direktifleri yalnızca işlevsellik için gerekli temel stilleri uygular. Uygulamalar, bu belirtilen CSS sınıflarını hedefleyerek stillerini özelleştirebilir.
CSS class name
Description
.cdk-drop-list
cdkDropList kapsayıcı öğeleri için seçici.
.cdk-drag
cdkDrag öğeleri için seçici.
.cdk-drag-disabled
Devre dışı bırakılmış cdkDrag öğeleri için seçici.
.cdk-drag-handle
cdkDragHandle'ın host öğesi için seçici.
.cdk-drag-preview
Sürükleme önizleme öğesi için seçici. Bu, kullanıcı sıralanabilir bir listede öğe sürüklerken imlecin yanında görünen öğedir.
Öğe, *cdkDragPreview aracılığıyla özel bir şablonla özelleştirilmedikçe sürüklenen öğeyle tamamen aynı görünür.
.cdk-drag-placeholder
Sürükleme yer tutucu öğesi için seçici. Bu, sürükleme eylemi sona erdiğinde sürüklenebilir öğenin sürükleneceği noktada gösterilen öğedir.
Bu öğe, cdkDragPlaceholder direktifiyle özelleştirilmedikçe sıralanan öğeyle tamamen aynı görünür.
.cdk-drop-list-dragging
Şu anda sürüklenmekte olan bir sürüklenebilir öğeye sahip cdkDropList kapsayıcı öğesi için seçici.
.cdk-drop-list-disabled
Devre dışı bırakılmış cdkDropList kapsayıcı öğeleri için seçici.
.cdk-drop-list-receiving
Şu anda sürüklenmekte olan bağlı bir bırakma listesinden alabileceği bir sürüklenebilir öğeye sahip cdkDropList kapsayıcı öğesi için seçici.
.cdk-drag-anchor
cdkDropListHasAnchor etkinleştirildiğinde oluşturulan çapa öğesi için seçici. Bu öğe, sürüklenen öğenin başladığı konumu gösterir.
Sürüklenebilir öğeleriniz kaydırılabilir bir kapsayıcı içindeyse (örneğin, overflow: auto ile bir div), kaydırılabilir kapsayıcıda cdkScrollable direktifi olmadıkça otomatik kaydırma çalışmaz. Bu olmadan CDK, sürükleme işlemleri sırasında kapsayıcının kaydırma davranışını algılayamaz veya kontrol edemez.
CDK'nin sürükle ve bırak işlevselliği farklı bileşenlerle entegre edilebilir. Yaygın kullanım durumları arasında sıralanabilir MatTable bileşenleri ve sıralanabilir MatTabGroup bileşenleri bulunur.