Skip to content

Commit f3bb0c7

Browse files
crisbetojelbourn
authored andcommitted
fix(drag-drop): emitting incorrect index for horizontal list in rtl (#13274)
Fixes the wrong index being emitted if the list is horizontal in an RTL layout.
1 parent 10e6502 commit f3bb0c7

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

src/cdk/drag-drop/drag.spec.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,45 @@ describe('CdkDrag', () => {
569569
.toEqual(['One', 'Two', 'Zero', 'Three']);
570570
}));
571571

572+
it('should dispatch the correct `dropped` event in RTL horizontal drop zone', fakeAsync(() => {
573+
const fixture = createComponent(DraggableInHorizontalDropZone, [{
574+
provide: Directionality,
575+
useValue: ({value: 'rtl'})
576+
}]);
577+
578+
fixture.nativeElement.setAttribute('dir', 'rtl');
579+
fixture.detectChanges();
580+
const dragItems = fixture.componentInstance.dragItems;
581+
582+
expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim()))
583+
.toEqual(['Zero', 'One', 'Two', 'Three']);
584+
585+
const firstItem = dragItems.first;
586+
const thirdItemRect = dragItems.toArray()[2].element.nativeElement.getBoundingClientRect();
587+
588+
dragElementViaMouse(fixture, firstItem.element.nativeElement,
589+
thirdItemRect.right - 1, thirdItemRect.top + 1);
590+
flush();
591+
fixture.detectChanges();
592+
593+
expect(fixture.componentInstance.droppedSpy).toHaveBeenCalledTimes(1);
594+
595+
const event = fixture.componentInstance.droppedSpy.calls.mostRecent().args[0];
596+
597+
// Assert the event like this, rather than `toHaveBeenCalledWith`, because Jasmine will
598+
// go into an infinite loop trying to stringify the event, if the test fails.
599+
expect(event).toEqual({
600+
previousIndex: 0,
601+
currentIndex: 2,
602+
item: firstItem,
603+
container: fixture.componentInstance.dropInstance,
604+
previousContainer: fixture.componentInstance.dropInstance
605+
});
606+
607+
expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim()))
608+
.toEqual(['One', 'Two', 'Zero', 'Three']);
609+
}));
610+
572611
it('should not move items in a horizontal list if pointer is too far away', fakeAsync(() => {
573612
const fixture = createComponent(DraggableInHorizontalDropZone);
574613
fixture.detectChanges();

src/cdk/drag-drop/drop.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import {
2020
Output,
2121
QueryList,
2222
ViewEncapsulation,
23+
Optional,
2324
} from '@angular/core';
25+
import {Directionality} from '@angular/cdk/bidi';
2426
import {CdkDrag} from './drag';
2527
import {DragDropRegistry} from './drag-drop-registry';
2628
import {CdkDragDrop, CdkDragEnter, CdkDragExit} from './drag-events';
@@ -103,7 +105,8 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
103105

104106
constructor(
105107
public element: ElementRef<HTMLElement>,
106-
private _dragDropRegistry: DragDropRegistry<CdkDrag, CdkDrop<T>>) {}
108+
private _dragDropRegistry: DragDropRegistry<CdkDrag, CdkDrop<T>>,
109+
@Optional() private _dir?: Directionality) {}
107110

108111
ngOnInit() {
109112
this._dragDropRegistry.registerDropContainer(this);
@@ -217,9 +220,17 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
217220
* @param item Item whose index should be determined.
218221
*/
219222
getItemIndex(item: CdkDrag): number {
220-
return this._dragging ?
221-
findIndex(this._positionCache.items, currentItem => currentItem.drag === item) :
222-
this._draggables.toArray().indexOf(item);
223+
if (!this._dragging) {
224+
return this._draggables.toArray().indexOf(item);
225+
}
226+
227+
// Items are sorted always by top/left in the cache, however they flow differently in RTL.
228+
// The rest of the logic still stands no matter what orientation we're in, however
229+
// we need to invert the array when determining the index.
230+
const items = this.orientation === 'horizontal' && this._dir && this._dir.value === 'rtl' ?
231+
this._positionCache.items.slice().reverse() : this._positionCache.items;
232+
233+
return findIndex(items, currentItem => currentItem.drag === item);
223234
}
224235

225236
/**

0 commit comments

Comments
 (0)