我用的是Angular 10版本。我创建了一个自定义指令“FreeDraggingDirective”。我只是想在运行时将此指令附加到一个html元素。
这是appModule
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NgFlowchartModule } from 'projects/ng-flowchart/src/lib/ng-flowchart.module';
import { AppComponent } from './app.component';
import { CustomStepComponent } from './custom-step/custom-step.component';
import { RouteStepComponent } from './custom-step/route-step/route-step.component';
import { NestedFlowComponent } from './nested-flow/nested-flow.component';
import { FormStepComponent } from './form-step/form-step.component';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { MatIconModule, MatIconRegistry } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { GroupComponent } from './group/group.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
import { ToastrModule } from 'ngx-toastr';
import { FreeDraggingDirective } from './free-dragging.direcetive';
@NgModule({
declarations: [
AppComponent,
CustomStepComponent,
RouteStepComponent,
NestedFlowComponent,
FormStepComponent,
GroupComponent,FreeDraggingDirective
],
imports: [
BrowserModule,
NgFlowchartModule,
FormsModule,
MatMenuModule,
MatDialogModule,
MatTooltipModule,
MatButtonModule,
MatToolbarModule,
MatIconModule,
BrowserAnimationsModule,
ToastrModule.forRoot(), // ToastrModule added
],
exports: [
FormsModule,
FreeDraggingDirective,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
这是我的指令
import { DOCUMENT } from '@angular/common';
import {
AfterViewInit,
ContentChild,
Directive,
ElementRef,
Inject,
Input,
OnDestroy,
} from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';
import { max, takeUntil } from 'rxjs/operators';
@Directive({
selector: '.appFreeDragging',
})
export class FreeDraggingDirective implements AfterViewInit, OnDestroy {
private element: HTMLElement;
private subscriptions: Subscription[] = [];
// @ContentChild(FreeDraggingHandleDirective)
// handle: FreeDraggingHandleDirective;
handleElement: HTMLElement;
private readonly DEFAULT_DRAGGING_BOUNDARY_QUERY = '.ngflowchart-canvas';
@Input() boundaryQuery = this.DEFAULT_DRAGGING_BOUNDARY_QUERY;
draggingBoundaryElement: HTMLElement | HTMLBodyElement;
handle: any;
constructor(
private elementRef: ElementRef,
@Inject(DOCUMENT) private document: any
) {}
ngAfterViewInit(): void {
this.draggingBoundaryElement = (this.document as Document).querySelector(
'body'
);
if (!this.draggingBoundaryElement) {
throw new Error(
"Couldn't find any element with query: " + this.boundaryQuery
);
} else {
this.element = this.elementRef.nativeElement as HTMLElement;
this.handleElement =
this.handle?.elementRef?.nativeElement || this.element;
this.initDrag();
}
}
initDrag(): void {
const dragStart$ = fromEvent<MouseEvent>(this.handleElement, 'mousedown');
const dragEnd$ = fromEvent<MouseEvent>(this.document, 'mouseup');
const drag$ = fromEvent<MouseEvent>(this.document, 'mousemove').pipe(
takeUntil(dragEnd$)
);
let initialX: number,
initialY: number,
currentX = 0,
currentY = 0;
let dragSub: Subscription;
const minBoundX = this.draggingBoundaryElement.offsetLeft;
const minBoundY = this.draggingBoundaryElement.offsetTop;
const maxBoundX =
minBoundX +
this.draggingBoundaryElement.offsetWidth -
this.element.offsetWidth;
const maxBoundY =
minBoundY +
this.draggingBoundaryElement.offsetHeight -
this.element.offsetHeight;
const dragStartSub = dragStart$.subscribe((event: MouseEvent) => {
initialX = event.clientX - currentX;
initialY = event.clientY - currentY;
this.element.classList.add('free-dragging');
dragSub = drag$.subscribe((event: MouseEvent) => {
event.preventDefault();
const x = event.clientX - initialX;
const y = event.clientY - initialY;
currentX = x;
currentY = y;
this.element.style.transform =
'translate3d(' + currentX + 'px, ' + currentY + 'px, 0)';
});
});
const dragEndSub = dragEnd$.subscribe(() => {
initialX = currentX;
initialY = currentY;
this.element.classList.remove('free-dragging');
if (dragSub) {
dragSub.unsubscribe();
}
});
this.subscriptions.push.apply(this.subscriptions, [
dragStartSub,
dragSub,
dragEndSub,
]);
}
ngOnDestroy(): void {
this.subscriptions.forEach((s) => s?.unsubscribe());
}
}
所以问题是当尝试在HTML上添加此指令时,它正在工作。
<div class="outerContent appFreeDragging" >
<!-- content inside here is draggable -->
</div>
但是当通过动态添加它来实现相同的效果时,它不起作用。
let outerContent = document.querySelector('outerContent');
outerContent.classList.add('appFreeDragging');
上面的代码在DOM中创建了一个类,但指令不起作用。有没有可能的方法来解决这个问题?
先谢谢你了。
1条答案
按热度按时间vxbzzdmp1#
显然它不会工作,组件加载上的angular bind指令