如何使用 @angular/cdk 使 NgbModal 可拖动
How to make NgbModal draggable with @angular/cdk
我在弄清楚如何使我的模态框可拖动时遇到了一些困难。我有可重复使用的模式,它有自己的服务,调用它来创建一个内部组件。
confirm.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
)
);
}
}
confirm.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 {}
confirm.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);
}
}
confirm.modal.component.html
<div class="modal-body">
<div class="modal-body__header">
<span>{{ title }}</span>
</div>
<div *ngIf="subtitle" class="modal-body__text">
<span>{{ subtitle }}</span>
</div>
<div class="modal-body__button-row">
<button class="btn btn-primary" (click)="accept()">Yes</button>
<button class="btn btn-light" (click)="dismiss()">Cancel</button>
</div>
</div>
所以我想让整个模式都可以拖动 Angular built-in DragDropModule, hence I should add cdkDrag
inside element with class='modal-content'
but I don't how to achieve that with current setup. NgbModalOptions 提供了仅添加 class 但不添加属性指令的功能。
我知道 JQuery 可拖动有更简单的解决方案,但我想避免这种情况。
我正在考虑对每个页面使用 @ViewChildren,但它似乎不是我的最佳解决方案。
感谢您的帮助!
只需将模态框包裹在一个容器中,然后按照 documentation 将 cdkDragRootElement 添加到其中。当您从 component.ts.
打开对话框时,您还必须添加此 class 作为选项
<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>
代码为component.ts
const options: NgbModalOptions = {
windowClass: 'your-custom-dialog-class'
};
this.modalService.open(this.content, options);
我在弄清楚如何使我的模态框可拖动时遇到了一些困难。我有可重复使用的模式,它有自己的服务,调用它来创建一个内部组件。
confirm.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
)
);
}
}
confirm.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 {}
confirm.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);
}
}
confirm.modal.component.html
<div class="modal-body">
<div class="modal-body__header">
<span>{{ title }}</span>
</div>
<div *ngIf="subtitle" class="modal-body__text">
<span>{{ subtitle }}</span>
</div>
<div class="modal-body__button-row">
<button class="btn btn-primary" (click)="accept()">Yes</button>
<button class="btn btn-light" (click)="dismiss()">Cancel</button>
</div>
</div>
所以我想让整个模式都可以拖动 Angular built-in DragDropModule, hence I should add cdkDrag
inside element with class='modal-content'
but I don't how to achieve that with current setup. NgbModalOptions 提供了仅添加 class 但不添加属性指令的功能。
我知道 JQuery 可拖动有更简单的解决方案,但我想避免这种情况。
我正在考虑对每个页面使用 @ViewChildren,但它似乎不是我的最佳解决方案。
感谢您的帮助!
只需将模态框包裹在一个容器中,然后按照 documentation 将 cdkDragRootElement 添加到其中。当您从 component.ts.
打开对话框时,您还必须添加此 class 作为选项<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>
代码为component.ts
const options: NgbModalOptions = {
windowClass: 'your-custom-dialog-class'
};
this.modalService.open(this.content, options);