Skip to content

Commit e87de13

Browse files
authored
fix(drag-drop): detect changes on custom preview/placeholder before measuring (#18698)
When a custom preview/placeholder is created, its dimensions are measured so that they can be used while sorting. The problem is that we weren't detecting changes after creation which can cause the dimensions to be incorrect, if they change based on a data binding. These changes check for changes after inserting the embedded view. Fixes #18622.
1 parent eb92de8 commit e87de13

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

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

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3010,6 +3010,30 @@ describe('CdkDrag', () => {
30103010
expect(placeholder.textContent!.trim()).not.toContain('Custom placeholder');
30113011
}));
30123012

3013+
it('should measure the custom placeholder after the first change detection', fakeAsync(() => {
3014+
const fixture = createComponent(DraggableInDropZoneWithCustomPlaceholder);
3015+
fixture.componentInstance.extraPlaceholderClass = 'tall-placeholder';
3016+
fixture.detectChanges();
3017+
const dragItems = fixture.componentInstance.dragItems;
3018+
const item = dragItems.toArray()[0].element.nativeElement;
3019+
3020+
startDraggingViaMouse(fixture, item);
3021+
3022+
const thirdItem = dragItems.toArray()[2].element.nativeElement;
3023+
const thirdItemRect = thirdItem.getBoundingClientRect();
3024+
3025+
dispatchMouseEvent(document, 'mousemove', thirdItemRect.left + 1, thirdItemRect.top + 1);
3026+
fixture.detectChanges();
3027+
3028+
dispatchMouseEvent(document, 'mouseup');
3029+
fixture.detectChanges();
3030+
flush();
3031+
fixture.detectChanges();
3032+
3033+
const event = fixture.componentInstance.droppedSpy.calls.mostRecent().args[0];
3034+
expect(event.currentIndex).toBe(2);
3035+
}));
3036+
30133037
it('should not throw when custom placeholder only has text', fakeAsync(() => {
30143038
const fixture = createComponent(DraggableInDropZoneWithCustomTextOnlyPlaceholder);
30153039
fixture.detectChanges();
@@ -5127,21 +5151,34 @@ class DraggableInDropZoneWithCustomTextOnlyPreview {
51275151

51285152
@Component({
51295153
template: `
5130-
<div cdkDropList style="width: 100px; background: pink;">
5154+
<div
5155+
cdkDropList
5156+
(cdkDropListDropped)="droppedSpy($event)"
5157+
style="width: 100px; background: pink;">
51315158
<div *ngFor="let item of items" cdkDrag
51325159
style="width: 100%; height: ${ITEM_HEIGHT}px; background: red;">
51335160
{{item}}
51345161
<ng-container *ngIf="renderPlaceholder">
5135-
<div class="custom-placeholder" *cdkDragPlaceholder>Custom placeholder</div>
5162+
<div
5163+
class="custom-placeholder"
5164+
[ngClass]="extraPlaceholderClass"
5165+
*cdkDragPlaceholder>Custom placeholder</div>
51365166
</ng-container>
51375167
</div>
51385168
</div>
5139-
`
5169+
`,
5170+
styles: [`
5171+
.tall-placeholder {
5172+
height: ${ITEM_HEIGHT * 3}px;
5173+
}
5174+
`]
51405175
})
51415176
class DraggableInDropZoneWithCustomPlaceholder {
51425177
@ViewChildren(CdkDrag) dragItems: QueryList<CdkDrag>;
51435178
items = ['Zero', 'One', 'Two', 'Three'];
51445179
renderPlaceholder = true;
5180+
extraPlaceholderClass = '';
5181+
droppedSpy = jasmine.createSpy('dropped spy');
51455182
}
51465183

51475184
@Component({

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ export class DragRef<T = any> {
884884
if (previewTemplate) {
885885
const viewRef = previewConfig!.viewContainer.createEmbeddedView(previewTemplate,
886886
previewConfig!.context);
887+
viewRef.detectChanges();
887888
preview = getRootNode(viewRef, this._document);
888889
this._previewRef = viewRef;
889890

@@ -984,6 +985,7 @@ export class DragRef<T = any> {
984985
placeholderTemplate,
985986
placeholderConfig!.context
986987
);
988+
this._placeholderRef.detectChanges();
987989
placeholder = getRootNode(this._placeholderRef, this._document);
988990
} else {
989991
placeholder = deepCloneNode(this._rootElement);

0 commit comments

Comments
 (0)