Skip to content

fix(drag-drop): item not being restored to its initial DOM position when using custom preview #12808

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/cdk/drag-drop/drag.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,25 @@ describe('CdkDrag', () => {
expect(preview.textContent!.trim()).toContain('Custom preview');
}));

it('should revert the element back to its parent after dragging with a custom ' +
'preview has stopped', fakeAsync(() => {
const fixture = createComponent(DraggableInDropZoneWithCustomPreview);
fixture.detectChanges();

const dragContainer = fixture.componentInstance.dropInstance.element.nativeElement;
const item = fixture.componentInstance.dragItems.toArray()[1].element.nativeElement;

expect(dragContainer.contains(item)).toBe(true, 'Expected item to be in container.');

// The coordinates don't matter.
dragElementViaMouse(fixture, item, 10, 10);
flush();
fixture.detectChanges();

expect(dragContainer.contains(item))
.toBe(true, 'Expected item to be returned to container.');
}));

it('should position custom previews next to the pointer', fakeAsync(() => {
const fixture = createComponent(DraggableInDropZoneWithCustomPreview);
fixture.detectChanges();
Expand Down
6 changes: 5 additions & 1 deletion src/cdk/drag-drop/drag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,18 @@ export class CdkDrag<T = any> implements OnDestroy {

if (this.dropContainer) {
const element = this.element.nativeElement;

// Grab the `nextSibling` before the preview and placeholder
// have been created so we don't get the preview by accident.
this._nextSibling = element.nextSibling;

const preview = this._preview = this._createPreviewElement();
const placeholder = this._placeholder = this._createPlaceholderElement();

// We move the element out at the end of the body and we make it hidden, because keeping it in
// place will throw off the consumer's `:last-child` selectors. We can't remove the element
// from the DOM completely, because iOS will stop firing all subsequent events in the chain.
element.style.display = 'none';
this._nextSibling = element.nextSibling;
this._document.body.appendChild(element.parentNode!.replaceChild(placeholder, element));
this._document.body.appendChild(preview);
this.dropContainer.start();
Expand Down
2 changes: 1 addition & 1 deletion src/lib/progress-bar/progress-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export class MatProgressBar extends _MatProgressBarMixinBase implements CanColor
// `Location` from `@angular/common` since we can't tell the difference between whether
// the consumer is using the hash location strategy or not, because `Location` normalizes
// both `/#/foo/bar` and `/foo/bar` to the same thing.
const path = location ? location.pathname.split('#')[0] : '';
const path = location && location.pathname ? location.pathname.split('#')[0] : '';
this._rectangleFillValue = `url('${path}#${this.progressbarId}')`;
}

Expand Down