如何使用@angular/cdk 使 NgbModal 可拖动

Nik*_*pov 5 html javascript draggable typescript angular

我在弄清楚如何使我的模态可拖动时遇到了一些困难。我有可重用的模态及其自己的服务,该服务被调用以创建一个内部组件。

确认.modal.service.ts

import { Injectable } from "@angular/core";
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
import { Observable, from, EMPTY, throwError } from "rxjs";
import { catchError, tap } from "rxjs/operators";

import { ConfirmModalComponent } from "./confirm-modal.component";

export interface ConfirmOptions {
    title: string;
    subtitle?: string;
    errorOnClose?: boolean;
}

@Injectable({ providedIn: "root" })
export class ConfirmModalService {
    constructor(private modalService: NgbModal) {}

    confirm(options: ConfirmOptions): Observable<boolean> {
        const modalRef = this.modalService.open(ConfirmModalComponent, {
            centered: true
        });
        modalRef.componentInstance.title = options.title || "Are you sure?";
        modalRef.componentInstance.subtitle = options.subtitle || null;

        return from(modalRef.result).pipe(
            tap(),
            catchError(err =>
                options.errorOnClose
                    ? throwError(err || "not confirmed")
                    : EMPTY
            )
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

确认.modal.module.ts

import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { DragDropModule } from "@angular/cdk/drag-drop";

import { ConfirmModalComponent } from "./confirm-modal.component";

@NgModule({
    imports: [
        CommonModule,
        DragDropModule
    ],
    declarations: [ConfirmModalComponent],
    exports: [ConfirmModalComponent]
})
export class ConfirmModalModule {}
Run Code Online (Sandbox Code Playgroud)

确认.modal.component.ts

import { Component, Input } from "@angular/core";
import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap";

@Component({
    selector: "app-confirm-modal",
    templateUrl: "./confirm-modal.component.html",
    styleUrls: ["./confirm-modal.component.scss"]
})
export class ConfirmModalComponent {
    @Input() title: string;
    @Input() subtitle: string;

    constructor(public activeModal: NgbActiveModal) {}

    public accept(): void {
        this.activeModal.close(true);
    }

    public dismiss(): void {
        this.activeModal.close(false);
    }
}
Run Code Online (Sandbox Code Playgroud)

确认.modal.component.html

import { Injectable } from "@angular/core";
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
import { Observable, from, EMPTY, throwError } from "rxjs";
import { catchError, tap } from "rxjs/operators";

import { ConfirmModalComponent } from "./confirm-modal.component";

export interface ConfirmOptions {
    title: string;
    subtitle?: string;
    errorOnClose?: boolean;
}

@Injectable({ providedIn: "root" })
export class ConfirmModalService {
    constructor(private modalService: NgbModal) {}

    confirm(options: ConfirmOptions): Observable<boolean> {
        const modalRef = this.modalService.open(ConfirmModalComponent, {
            centered: true
        });
        modalRef.componentInstance.title = options.title || "Are you sure?";
        modalRef.componentInstance.subtitle = options.subtitle || null;

        return from(modalRef.result).pipe(
            tap(),
            catchError(err =>
                options.errorOnClose
                    ? throwError(err || "not confirmed")
                    : EMPTY
            )
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我想使用Angular 内置的 DragDropModule使整个模态可拖动,因此我应该添加cdkDrag内部元素,class='modal-content'但我不知道如何使用当前设置来实现。NgbModalOptions提供仅添加类但不添加属性指令的功能。我知道 JQuery 可拖动有更简单的解决方案,但我想避免这种情况。

我在考虑使用@ViewChildren为每个页面,但这对我来说似乎不是最好的解决方案。

谢谢你的帮助!

Lou*_*med 4

只需将模态框包装在容器内,然后按照文档将 cdkDragRootElement 添加到其中即可。当您从 component.ts 打开对话框时,您还必须添加此类作为选项。

<ng-template #content
  let-modal>
    <div
      cdkDrag
      cdkDragRootElement=".your-custom-dialog-class">
      <div class="modal-header">
    
      </div>
      <div class="modal-body">
    
      </div>
    
      <div class="modal-footer">
      </div>
    </div>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

component.ts 的代码

const options: NgbModalOptions = {
windowClass: 'your-custom-dialog-class'
};
this.modalService.open(this.content, options);
Run Code Online (Sandbox Code Playgroud)