Skip to content

Commit

Permalink
feat: enhance modal dialog component with fullscreen and scrolling (#…
Browse files Browse the repository at this point in the history
…1350)

* add support for fullscreen modal styling (similar to Bootstrap 5), use `modalDialogClass: 'modal-fullscreen'` instead of `size`
* add `scrollToAnchor` method for automatic scrolling within a dialog
* extend support for all `NgbModalOptions` (not only `size`)
  • Loading branch information
SGrueber authored and shauke committed Apr 6, 2023
1 parent 3486687 commit 1de7672
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,14 @@ import {
TemplateRef,
ViewChild,
} from '@angular/core';
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { NgbModal, NgbModalOptions, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { Subject, take, takeUntil } from 'rxjs';

export interface ModalOptions {
export interface ModalOptions extends NgbModalOptions {
/**
* Modal title string.
*/
titleText: string;
/**
* size attribute
* 'sm': small, 'lg': large, 'xl': extra large, 'md': medium (default)
*/
size?: 'sm' | 'lg' | 'xl';
titleText?: string;
/**
* Optional modal confirm button text.
*/
Expand All @@ -36,11 +31,13 @@ export interface ModalOptions {
}

/**
* The Modal Dialog Component displays a generic modal, that shows a custom title and custom content.
* The Modal Dialog Component displays a generic (ng-bootstrap) modal, that shows a custom title and custom content.
* It provides an optional footer that includes confirm and reject buttons.
* It is possible to pass any data on show.
* The also provided confirmed output emitter will return the previously passed data if the modal gets confirmed.
*
* @see https://ng-bootstrap.github.io/#/components/modal/api#NgbModal
*
* @example
* <ish-modal-dialog [options]="options" (confirmed)="onConfirmed($event)">
* Dummy content
Expand Down Expand Up @@ -74,13 +71,9 @@ export class ModalDialogComponent<T> implements OnDestroy {
* Configure and show modal dialog.
*/
show(data?: T) {
if (data) {
this.data = data;
}

const size = this.options?.size ? this.options.size : undefined;
this.data = data ? data : undefined;

this.ngbModalRef = this.ngbModal.open(this.modalDialogTemplate, { size });
this.ngbModalRef = this.ngbModal.open(this.modalDialogTemplate, this.options);

this.ngbModalRef.dismissed.pipe(take(1), takeUntil(this.destroy$)).subscribe(() => this.closed.emit(this.data));

Expand All @@ -104,6 +97,22 @@ export class ModalDialogComponent<T> implements OnDestroy {
this.hide();
}

/**
* Scrolls to an anchor element
*
* @param anchor The ID of the anchor element.
*/
scrollToAnchor(anchor: string) {
if (this.options.scrollable) {
const element = document.getElementById(anchor);
if (element) {
setTimeout(() => {
element.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' });
}, 200);
}
}
}

ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
Expand Down
43 changes: 43 additions & 0 deletions src/styles/global/modals.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,46 @@
}
}
}

// fullscreen modal styling (similar to Bootstrap 5)
// use `modalDialogClass: 'modal-fullscreen'` instead of `size`
.modal-fullscreen {
min-width: 100%;
margin: 0;

.modal-content {
min-height: 100vh;
padding-top: 50px; // for the fixed header
border: none;
}

// the fixed header in fullscreen is needed for mobile devices
// otherwise the header will not always be reachable to close the dialog
.modal-header {
position: fixed;
top: 0;
left: 0;
z-index: 1;
width: 100%;
min-height: 50px;
background-color: $color-inverse;
}

.modal-body {
align-self: center;
}
}

.modal-dialog-scrollable {
min-height: 100vh;

.modal-body {
// Hide scrollbar for Firefox
scrollbar-width: none;

/* Hide scrollbar for WebKit browsers */
&::-webkit-scrollbar {
display: none;
}
}
}

0 comments on commit 1de7672

Please sign in to comment.