modalicious v1.0.0
Modalicious
A bare-bones modal service for Angular which gives you full control over the actual modal window's appearance.
Installation
npm i -S modalicious
Usage
Setup
Choose between fixed positioning or absolute. Absolute is recommended as mobile safari has issues rending text fields in fixed position elements and the work-arounds force the user to the top of the page when a modal is opened. For absolute positioning you will need to apply the following styles to force scroll bars to appear in the root component instead of the body.
/* style.scss */
html, body {
height: 100%;
overflow: hidden;
padding: 0;
margin: 0;
}/* app.component.scss */
:host {
overflow-y: auto;
overflow-x: hidden;
height: 100%;
display: block;
}Config
Import the module
/* app.module.ts */
@NgModule({
...
imports: [
...,
BrowserAnimationsModule, // Import animations module if you have not already
// NoopAnimationsModule, // Or import NoopAnimationsModule if you do not want animations
ModaliciousModule.forRoot()
],
bootstrap: [AppComponent]
})
export class AppModule {
}Set the root view container ref and optionally change modal positioning
/* app.component.ts */
export class AppComponent {
constructor(private modalService: ModalService,
viewContainerRef: ViewContainerRef) {
this.modalService.setRootViewContainerRef(viewContainerRef);
// Can be omitted if using default of false.
this.modalService.setModalPositioning(/* useFixed */ false);
}
}Action!
Any directives you wish to use as a modal should be registered in your module as an entryComponent
/* app.module.ts */
@NgModule({
...
declarations: [
DemoModalComponent
],
entryComponents: [
DemoModalComponent
],
bootstrap: [AppComponent]
})Take a dependency on ModalService and call show()
export class AnyComponent {
constructor(private modalService: ModalService) {
}
async showTheDemoModal() {
// You can optionally await a response from the modal when it is closed (see below)
const res: number = await this.modalService.show< DemoModalComponent>(DemoModalComponent);
}
}Closing or cancelling a modal
In order to to close a modal and dispose of the rendered template you will need to resolve a ModalInstanceService in your
modal component and invoke one of the available methods. The optional resolve param will be passed back to the Promise
returned by ModalService.show(). Cancelling the modal will result in a rejected Promise.
/* demo-modal.component.ts */
export class DemoModalComponent {
constructor(private modalInstance: ModalInstanceService) {
}
close() {
this.modalInstance.resolve(/* Optional value to resolve */);
}
cancel() {
this.modalInstance.cancel('User cancelled');
}
}Close Modal directive
As a short-hand way of binding a click handler to an element to close a dialog, one can use the mod-close-modal directive
on any appropriate form element. The directive can be bound with an optional value to be returned to the resolve method.
<!-- demo-modal.component.html -->
<button class="close-button" mod-modal-close>X</button>
<p>
Modal text blah blah.
</p>
<button class="yes-button" [mod-modal-close]="'Yes'">Yes</button>Providing additional values to the modal
You can pass services to the modal component by taking a dependency on them as you usually would in the constructor,
then pass your own providers to the ModalService.Show() method. These providers will only be scoped to that modal.
For non-class dependencies you will need to use the @Inject annotation
/* demo-modal.component.ts */
export const DemoModalColor = new InjectionToken<string>('demo-modal.color');
export class DemoModalComponent implements OnInit {
@HostBinding('style.color') color: string;
constructor(private modalInstance: ModalInstanceService,
@Inject('name') public name: string,
@Inject(DemoModalColor) public color: string) {
}export class AnyComponent {
constructor(private modalService: ModalService) {
}
async showTheDemoModal() {
await this.modalService.show<DemoModalComponent>(DemoModalComponent, [
{ provide: 'name', useValue: 'Jimmy Two Shoes'},
{ provide: DemoModalColor, useValue: '#1140ff'}]);
}
}