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.
This commit is contained in:
Kristiyan Kostadinov
2018-09-27 16:16:44 +02:00
committed by Jeremy Elbourn
parent 10e6502147
commit f3bb0c7515
2 changed files with 54 additions and 4 deletions
+39
View File
@@ -569,6 +569,45 @@ describe('CdkDrag', () => {
.toEqual(['One', 'Two', 'Zero', 'Three']);
}));
it('should dispatch the correct `dropped` event in RTL horizontal drop zone', fakeAsync(() => {
const fixture = createComponent(DraggableInHorizontalDropZone, [{
provide: Directionality,
useValue: ({value: 'rtl'})
}]);
fixture.nativeElement.setAttribute('dir', 'rtl');
fixture.detectChanges();
const dragItems = fixture.componentInstance.dragItems;
expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim()))
.toEqual(['Zero', 'One', 'Two', 'Three']);
const firstItem = dragItems.first;
const thirdItemRect = dragItems.toArray()[2].element.nativeElement.getBoundingClientRect();
dragElementViaMouse(fixture, firstItem.element.nativeElement,
thirdItemRect.right - 1, thirdItemRect.top + 1);
flush();
fixture.detectChanges();
expect(fixture.componentInstance.droppedSpy).toHaveBeenCalledTimes(1);
const event = fixture.componentInstance.droppedSpy.calls.mostRecent().args[0];
// Assert the event like this, rather than `toHaveBeenCalledWith`, because Jasmine will
// go into an infinite loop trying to stringify the event, if the test fails.
expect(event).toEqual({
previousIndex: 0,
currentIndex: 2,
item: firstItem,
container: fixture.componentInstance.dropInstance,
previousContainer: fixture.componentInstance.dropInstance
});
expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim()))
.toEqual(['One', 'Two', 'Zero', 'Three']);
}));
it('should not move items in a horizontal list if pointer is too far away', fakeAsync(() => {
const fixture = createComponent(DraggableInHorizontalDropZone);
fixture.detectChanges();
+15 -4
View File
@@ -20,7 +20,9 @@ import {
Output,
QueryList,
ViewEncapsulation,
Optional,
} from '@angular/core';
import {Directionality} from '@angular/cdk/bidi';
import {CdkDrag} from './drag';
import {DragDropRegistry} from './drag-drop-registry';
import {CdkDragDrop, CdkDragEnter, CdkDragExit} from './drag-events';
@@ -103,7 +105,8 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
constructor(
public element: ElementRef<HTMLElement>,
private _dragDropRegistry: DragDropRegistry<CdkDrag, CdkDrop<T>>) {}
private _dragDropRegistry: DragDropRegistry<CdkDrag, CdkDrop<T>>,
@Optional() private _dir?: Directionality) {}
ngOnInit() {
this._dragDropRegistry.registerDropContainer(this);
@@ -217,9 +220,17 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
* @param item Item whose index should be determined.
*/
getItemIndex(item: CdkDrag): number {
return this._dragging ?
findIndex(this._positionCache.items, currentItem => currentItem.drag === item) :
this._draggables.toArray().indexOf(item);
if (!this._dragging) {
return this._draggables.toArray().indexOf(item);
}
// Items are sorted always by top/left in the cache, however they flow differently in RTL.
// The rest of the logic still stands no matter what orientation we're in, however
// we need to invert the array when determining the index.
const items = this.orientation === 'horizontal' && this._dir && this._dir.value === 'rtl' ?
this._positionCache.items.slice().reverse() : this._positionCache.items;
return findIndex(items, currentItem => currentItem.drag === item);
}
/**