我在放下文件时出现了两倍重叠的问题。
用户可以拖放文件。拖动文件时,在特定区域中应该有一个叠加层,上面显示消息“在此处拖动文件”(仅在可以放置文件的地方)。我写了一条指令来处理这种行为。
file-upload.directive.ts:
import { Overlay, OverlayRef, PositionStrategy } from '@angular/cdk/overlay';
import { TemplatePortal } from '@angular/cdk/portal';
import { ComponentFactoryResolver, Directive, Input, NgZone, OnDestroy, OnInit, TemplateRef, ViewContainerRef } from '@angular/core';
import { FileUploadComponent } from './file-upload.component';
import { Subject, Subscription } from 'rxjs';
@Directive({
selector: '[fileUpload]',
})
export class FileUploadDirective implements OnInit, OnDestroy {
private _overlayRef: OverlayRef;
private _onDestroy$ = new Subject();
private _dragEventsCollection = [];
private _fileUploadComponent: FileUploadComponent;
private _status: boolean = false;
constructor(
private _hostTemplate: TemplateRef<any>,
private _hostViewContainer: ViewContainerRef,
private _resolver: ComponentFactoryResolver,
private _overlayService: Overlay
) { }
ngOnInit(): void {
// Creating ng-template contents (host element)
this._hostViewContainer.createEmbeddedView(this._hostTemplate);
// Creating file-drop component
this._fileUploadComponent = this._hostViewContainer
.createComponent(this._resolver.resolveComponentFactory(FileUploadComponent))
.instance;
document.addEventListener('dragenter', e => {
console.log('dragEventCollection.length: ', this._dragEventsCollection.length);
if (this._dragEventsCollection.length === 0) {
console.warn('Opening overlay. Event: ', e);
this.openOverlay();
// this removes the second event - however the second event triggers correct overlay and the first one not
// e.stopImmediatePropagation() ;
}
this._dragEventsCollection.push(e.target);
});
document.addEventListener('dragleave', e => {
const index = this._dragEventsCollection.indexOf(e.target);
this._dragEventsCollection.splice(index, 1);
if (this._dragEventsCollection.length === 0) {
this.closeOverlay();
}
});
}
ngOnDestroy(): void {
this._onDestroy$.next();
this._onDestroy$.unsubscribe();
this._onDestroy$ = null;
}
openOverlay() {
const cdkOverlayOrigin = this._hostTemplate.elementRef.nativeElement.nextElementSibling;
let positionStrategy: PositionStrategy;
if (this._overlayRef === undefined) {
positionStrategy = this._overlayService.position()
.flexibleConnectedTo(cdkOverlayOrigin)
.withPush(false)
.withGrowAfterOpen(true)
.withPositions([{
originX: 'start',
originY: 'top',
overlayX: 'start',
overlayY: 'top',
}]);
this._overlayRef = this._overlayService.create({
positionStrategy,
scrollStrategy: this._overlayService.scrollStrategies.block(),
});
}
if (!!this._overlayRef && !this._overlayRef.hasAttached()) {
this._overlayRef.attach(new TemplatePortal(this._fileUploadComponent.overlayTemplate, this._hostViewContainer));
this._overlayRef.updateSize({
width: cdkOverlayOrigin.clientWidth,
height: cdkOverlayOrigin.clientHeight
}
);
}
console.warn('OverlayRef: ', this._overlayRef);
}
closeOverlay() {
if (!!this._overlayRef && this._overlayRef.hasAttached()) {
this._overlayRef.detach();
}
}
}
我注意到Dragenter事件触发了两次,这导致创建了两个覆盖面板:
这发生在Angular 7和8上。
具有完整示例代码的https://stackblitz.com/edit/epxansion-with-overlay-3-8esk4u
已经花费了几个小时试图弄清楚发生了什么。任何想法将不胜感激。
谢谢!