Skip to content

Commit

Permalink
feat(modal): add a 'fullscreen' option
Browse files Browse the repository at this point in the history
Fixes #4298
  • Loading branch information
maxokorokov committed Apr 28, 2022
1 parent cae915a commit 6d6189b
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/modal/modal-config.spec.ts
Expand Up @@ -18,6 +18,7 @@ describe('NgbModalConfig', () => {
expect(config.centered).toBeUndefined();
expect(config.container).toBeUndefined();
expect(config.injector).toBeUndefined();
expect(config.fullscreen).toBe(false);
expect(config.keyboard).toBe(true);
expect(config.scrollable).toBeUndefined();
expect(config.size).toBeUndefined();
Expand Down
12 changes: 12 additions & 0 deletions src/modal/modal-config.ts
Expand Up @@ -64,6 +64,17 @@ export interface NgbModalOptions {
*/
container?: string | HTMLElement;

/**
* If `true` modal will always be displayed in fullscreen mode.
*
* For values like `'md'` it means that modal will be displayed in fullscreen mode
* only if the viewport width is below `'md'`. For custom strings (ex. when passing `'mysize'`)
* it will add a `'modal-fullscreen-mysize-down'` class.
*
* If not specified will be `false`.
*/
fullscreen?: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string;

/**
* The `Injector` to use for modal content.
*/
Expand Down Expand Up @@ -124,6 +135,7 @@ export class NgbModalConfig implements Required<NgbModalOptions> {
beforeDismiss: () => boolean | Promise<boolean>;
centered: boolean;
container: string | HTMLElement;
fullscreen: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string = false;
injector: Injector;
keyboard = true;
scrollable: boolean;
Expand Down
4 changes: 2 additions & 2 deletions src/modal/modal-stack.ts
Expand Up @@ -31,8 +31,8 @@ export class NgbModalStack {
private _backdropAttributes = ['animation', 'backdropClass'];
private _modalRefs: NgbModalRef[] = [];
private _windowAttributes = [
'animation', 'ariaLabelledBy', 'ariaDescribedBy', 'backdrop', 'centered', 'keyboard', 'scrollable', 'size',
'windowClass', 'modalDialogClass'
'animation', 'ariaLabelledBy', 'ariaDescribedBy', 'backdrop', 'centered', 'fullscreen', 'keyboard', 'scrollable',
'size', 'windowClass', 'modalDialogClass'
];
private _windowCmpts: ComponentRef<NgbModalWindow>[] = [];
private _activeInstances: EventEmitter<NgbModalRef[]> = new EventEmitter();
Expand Down
18 changes: 18 additions & 0 deletions src/modal/modal-window.spec.ts
Expand Up @@ -32,6 +32,24 @@ describe('ngb-modal-dialog', () => {
expect(dialogEl).toHaveCssClass('modal-sm');
});

it('should render default modal window with a specified fullscreen size', () => {
fixture.detectChanges();
const dialogEl = fixture.nativeElement.querySelector('.modal-dialog') as HTMLElement;
expect(dialogEl).not.toHaveCssClass('modal-fullscreen');

fixture.componentInstance.fullscreen = true;
fixture.detectChanges();
expect(dialogEl).toHaveCssClass('modal-fullscreen');

fixture.componentInstance.fullscreen = 'sm';
fixture.detectChanges();
expect(dialogEl).toHaveCssClass('modal-fullscreen-sm-down');

fixture.componentInstance.fullscreen = 'custom';
fixture.detectChanges();
expect(dialogEl).toHaveCssClass('modal-fullscreen-custom-down');
});

it('should render default modal window with a specified class', () => {
fixture.componentInstance.windowClass = 'custom-class';
fixture.detectChanges();
Expand Down
10 changes: 8 additions & 2 deletions src/modal/modal-window.ts
Expand Up @@ -20,7 +20,7 @@ import {getFocusableBoundaryElements} from '../util/focus-trap';
import {Key} from '../util/key';
import {ModalDismissReasons} from './modal-dismiss-reasons';
import {ngbRunTransition, NgbTransitionOptions} from '../util/transition/ngbTransition';
import {reflow} from '../util/util';
import {isString, reflow} from '../util/util';

@Component({
selector: 'ngb-modal-window',
Expand All @@ -35,7 +35,7 @@ import {reflow} from '../util/util';
},
template: `
<div #dialog [class]="'modal-dialog' + (size ? ' modal-' + size : '') + (centered ? ' modal-dialog-centered' : '') +
(scrollable ? ' modal-dialog-scrollable' : '') + (modalDialogClass ? ' ' + modalDialogClass : '')" role="document">
fullscreenClass + (scrollable ? ' modal-dialog-scrollable' : '') + (modalDialogClass ? ' ' + modalDialogClass : '')" role="document">
<div class="modal-content"><ng-content></ng-content></div>
</div>
`,
Expand All @@ -54,6 +54,7 @@ export class NgbModalWindow implements OnInit,
@Input() ariaDescribedBy: string;
@Input() backdrop: boolean | string = true;
@Input() centered: string;
@Input() fullscreen: string | boolean;
@Input() keyboard = true;
@Input() scrollable: string;
@Input() size: string;
Expand All @@ -68,6 +69,11 @@ export class NgbModalWindow implements OnInit,
constructor(
@Inject(DOCUMENT) private _document: any, private _elRef: ElementRef<HTMLElement>, private _zone: NgZone) {}

get fullscreenClass(): string {
return this.fullscreen === true ? ' modal-fullscreen' :
isString(this.fullscreen) ? ` modal-fullscreen-${this.fullscreen}-down` : '';
}

dismiss(reason): void { this.dismissEvent.emit(reason); }

ngOnInit() {
Expand Down
35 changes: 35 additions & 0 deletions src/modal/modal.spec.ts
Expand Up @@ -583,6 +583,41 @@ describe('ngb-modal', () => {

});

describe('fullscreen options', () => {
it('should render modals with fullscreen === true', () => {
const modalInstance = fixture.componentInstance.open('foo', {fullscreen: true});
fixture.detectChanges();
expect(fixture.nativeElement).toHaveModal('foo');
expect(document.querySelector('.modal-dialog')).toHaveCssClass('modal-fullscreen');

modalInstance.close();
fixture.detectChanges();
expect(fixture.nativeElement).not.toHaveModal();
});

it('should render modals with specified fullscreen size', () => {
const modalInstance = fixture.componentInstance.open('foo', {fullscreen: 'sm'});
fixture.detectChanges();
expect(fixture.nativeElement).toHaveModal('foo');
expect(document.querySelector('.modal-dialog')).toHaveCssClass('modal-fullscreen-sm-down');

modalInstance.close();
fixture.detectChanges();
expect(fixture.nativeElement).not.toHaveModal();
});

it('should render modals with any string as fullscreen size', () => {
const modalInstance = fixture.componentInstance.open('foo', {fullscreen: 'blah'});
fixture.detectChanges();
expect(fixture.nativeElement).toHaveModal('foo');
expect(document.querySelector('.modal-dialog')).toHaveCssClass('modal-fullscreen-blah-down');

modalInstance.close();
fixture.detectChanges();
expect(fixture.nativeElement).not.toHaveModal();
});
});

describe('window custom class options', () => {

it('should render modals with the correct window custom classes', () => {
Expand Down

0 comments on commit 6d6189b

Please sign in to comment.