@mediacologne/ng-modal
v13.1.0
Published
- Updated Module to 7.0.0 to support angular 7.x.x and improve documentation
Downloads
24
Readme
News
- Updated Module to 7.0.0 to support angular 7.x.x and improve documentation
Installation
Install the NPM Module
$ npm install @mediacologne/ng-modal
Using the Library
After the installation add the module to your application module
// Import your library
import { ModalModule } from '@mediacologne/ng-modal';
@NgModule({
imports: [
ModalModule
]
})
export class AppModule { }
Documentation
Import Module with default Configuration
If you wan't to provide some default configuration for all Modals in you application, you can import the ModalModule
via the static forRoot()
method
and pass your defaultConfiguration
as parameter.
You can define every possible config option here!
For example:
// Import your library
import { ModalModule } from '@mediacologne/ng-modal';
@NgModule({
imports: [
ModalModule.forRoot(<IModalConfig>{
modal: {
defaultConfig: {
draggable: true,
cssStyle: {
'width': '80vw',
'modal-header': {
'height': '40px',
'border-color': '#2f2f2f'
},
'modal-title': {
'margin-top': '-10px',
'font-size': '1.1rem'
},
'modal-content': {
'background-color': '#535353'
}
}
}
}
}),
]
})
export class AppModule { }
All Possible configuration options:
{
title: 'Modal Header',
titleIcon: null,
bodyIcon: null,
body: '',
width: '600px',
template: null,
draggable: false,
backdropCloseable: false,
cssStyle: {},
component: <Component>,
componentParams: {},
onClose: null,
btnOk: 'OK',
btnCancel: 'Abbrechen',
btnOkVisible: true,
btnCancelVisible: true,
buttons: [ // only allowed for Confirmation-Modals
{result: 'yes', title: 'Yes', classes: ['btn-warning', 'btn-lg']},
],
options: [ // only allowed for Choose-Modals
{result: 'Sheldon Cooper', title: 'Sheldon Cooper'},
{result: {firstname: 'Howard', name: 'Wolowitz'}, title: 'Howard Wolowitz'}
]
}
Concepts
Next step is to add the Component <modal-container></modal-container>
before closing </body>
......
<modal-container></modal-container>
</body>
The Modal Container Component is holding a list of opened Modals (nested or rather child Modals are supported).
Opening Modals
Alert
ModalUtils.alert({
title: "Alert Title",
body: "Body Text"
}).then((result: any) => {
console.log(result);
});
Prompt
ModalUtils.prompt({
title: "Prompt Title",
body: "Body Text",
promptValue: 'vordefinierter Wert',
}).then((result: any) => {
console.log(result);
if (result == false) {
// Modal was canceled
}
else {
// result => written text
}
});
Confirm
ModalUtils.confirm({
title: "Confirm Title",
body: "Body Text"
}).then((result: any) => {
console.log(result);
if (result) {
// Modal was closed positive
}
else {
// Modal was closed negative
}
});
Choose
ModalUtils.choose({
title: "Choose Title",
body: "Body Text",
optionType: 'checkbox', // Supported: checkbox and dropdown; default: checkbox
options: [
{result: 'Sheldon Cooper', title: 'Sheldon Cooper'},
{result: {firstname: 'Howard', name: 'Wolowitz'}, title: 'Howard Wolowitz', selected: true, disabled: false} // preselect an option via select or via checked
]
}).then((result: any) => {
console.log(result); // Contains an Array with the selected results
// for example: ['Sheldon Cooper', {firstname: 'Howard', name: 'Wolowitz'}]
});
Component
ModalUtils.component({
title: "Component Title",
component: ModalableTestComponent,
componentParams: {
email: "[email protected]"
}
}).then((result: any) => {
console.log(result);
if (result.closingResult) {
// Modal was closed positive
console.log(result.componentResult); // <-- this was returned by the Component
}
else {
// Modal was closed negative
}
});
Every Component which should be loadable inside a Modal must implements the Modalable
Interface and it's onModalClose(closingResult: boolean)
onModalOpen(params: any)
Members.
These Methods get's called on Modal opening and closing to pass data in or out.
Pass Component class as string
In some situations you may need to pass the component not as a class references but as a string name. To do so, you must register a dynamic component. See example below:
// Register your component
ModalUtils.registerDynamicComponent({'MyModalComponent': MyModalComponent});
// Open a dynamic registered modal component by string
ModalUtils.component({
title: "Component Title",
component: 'MyModalComponent',
})
Icons
You can add Font Awesome Icons both to the Modal Header and the Modal Body.
Icon in Modal Header
To set an Icon inside the Modal Header, pass it as Font Awesome css class in titleIcon
option
ModalUtils.alert({
title: 'Attention!',
titleIcon: 'fa fa-info'
})
Icon in Modal Body
If you pass a Font Awesome Icon as css class via bodyIcon
option. The bodyIcon will be automatically in a flex row.
ModalUtils.alert({
title: 'Attention!',
bodyIcon: 'fa fa-info'
})
Custom CSS Style
If you have to change the modal CSS, you can provide custom styles via config.cssStyle
.
For example change the default width_
ModalUtils.alert({
cssStyle: {
'width': '60vw'
}
})
The config.cssStyle
styles are applied to the div.modal-dialog
. If you want to style other parts of the Modal, you can just add these parts as sub-objects like this:
ModalUtils.alert({
cssStyle: {
'modal-dialog': {
'width': '60vw'
},
'modal-header': {
'background-color': 'red'
}
}
})
Draggable Modals
As default the draggable
feature is disabled. If you want to make your Modals draggable, you have to install @angular/cdk
library and import the DragDropModule
(import {DragDropModule} from '@angular/cdk/drag-drop';
).
Enabling the draggable feature via config.draggable: true
.
Additional Confirmation Buttons
If you need a Confirmation Modal but with more than an OK and Cancel button, you can pass a buttons: []
array in the following structure (see example below).
Attention: Per default the Confirmation Modal will return true
or false
as a boolean. If you use the buttons: []
array you have to set the result: any
for each button which will the closingResult.
ModalUtils.confirm({
title: "Confirm Title",
body: "Do you wan't to delete?",
buttons: [
{result: 'yes', title: 'Yes', classes: ['btn-warning', 'btn-lg']},
{result: 'no', title: 'No', classes: ['btn-primary', 'btn-lg']},
{result: 'maybe', title: 'Maybe (disabled)', classes: ['btn-danger', 'btn-lg'], disabled: true},
{result: 'yes_all', title: 'Yes for all'},
]
}).then((result: any) => {
console.log(result); // 'yes', 'no', 'yes_all', 'maybe' (is disabled and cannot occur)
});
Custom Templates
// xxx.component.ts file
@ViewChild('headerTemplate') headerTemplate: TemplateRef<any>;
@ViewChild('footerTemplate') footerTemplate: TemplateRef<any>;
@ViewChild('bodyTemplate') bodyTemplate: TemplateRef<any>;
ModalUtils.alert({
template: {
header: this.headerTemplate,
footer: this.footerTemplate,
body: this.bodyTemplate
}
}).then((result: any) => {
console.log(result);
});
// xxx.component.html file
<ng-template #headerTemplate let-context="context">
<h4 class="modal-title" style="color:red">Custom Modal Header!</h4>
</ng-template>
<ng-template #bodyTemplate>
<div class="alert alert-danger" role="alert">
<strong>Oh snap!</strong> This is a Custom Modal Body
<!-- How to access the Context? -->
{{(context | async)?.yourProperty}}
</div>
</ng-template>
<ng-template #footerTemplate let-modalCtrl="modalCtrl" let-context="context">
<button type="button" class="btn btn-primary" (click)="modalCtrl.close(true)">Custom Footer Button OK</button>
<button type="button" class="btn btn-primary" (click)="modalCtrl.close(false)">Custom Footer Button CANCEL</button>
</ng-template>
If you provide a modalFooter or a modalHeader (they must be ViewChilds
), your custom Buttons are responsible for closing the Modal via modalCtrl (which is passed through ngTemplateOutletContext).
Alternatively you can access your component e.g. public methods modalCtrl.component.customAction()
which then is responsible for closing the Modal via the modalCtrl.
There are two ways to provide a custom footer or header template
- Provide a
ViewChild
reference asconfig.template.header
orconfig.template.footer
(the<ng-template>
has to be placed into the parent component (in which you are open the modal))
- Provide a
- Don't provide a
ViewChild
viaconfig.template.header
orconfig.template.footer
but define a@ViewChild('footerTemplate') footerTemplate: TemplateRef<any>;
inside the the 'Modalable' component (the exact naming of the variable is important)
The library scans yourModalable
component for those variables and use them for custom footer/ header. If no such variables are found, the default footer/ header are shown
- Don't provide a
Completely Hide header/footer
If you want to completely hide the header/ footer, you have to pass false
as config.template.header
or config.template.footer
Access the Component context
inside the custom header/ footer
In both, the custom header and footer, you can access the self-defined context of the component.
Simply define the let-context="context"
inside the <ng-template>
(e.g. <ng-template #modalHeader let-context="context">
) and you are able
to access everything your own getContext()
method returns (the method must be placed inside you component).
Because the context
is an Observable (BehaviourSubject), it must be piped through the async
Pipe to access it's values inside your custom header/footer temaplte like this {{(context | async)?.yourProperty}}
Special case: Use the context
inside a non component modal (like confirm or prompt)
If your modal is a prompt, alert or confirm, the let-context="context"
gives you your config.context
. This is because a non-confirm modal doesn't have a component which
can implement the getContext()
method.
Accessing Modal from Content Component via ModalCtrl
If the onModalOpen Method defines a modalCtrl argument, the holding Modal will pass it's ControlUnit (Ctrl) to it
onModalOpen(params: any, modalCtrl: any) {
// Show Modal Config
conosole.log("Active Modal Config", modalCtrl.config);
// Modify Modal Config
modalCtrl.config.btnOk = "Speichern";
// Close the Modal with a positive result
modalCtrl.close(true);
}
Close Modal on Event
If the closeOn is defined inside config and is a subscribable object, the Model get's closed on an Event reception
openAlertWithCloseOnEvent() {
// Define the event for closing the Modal
let event: EventEmitter<any> = new EventEmitter();
ModalUtils.alert({
title: 'Ein Alert',
body: "Alert Body Text",
closeOn: event
}).then(function (result) {
console.log("Alert Result", result);
});
setTimeout(() => {
// Trigger the event so the Modal will be closed immediatly
event.next(true);
}, 3000);
}
OnOpen Event
If the OnOpen Callback is defined it will be called immediatly after the Modal will be shown. As argument the callback receives the ModalCtrl which can be used to control the Modal
openAlertWithOpenEvent() {
ModalUtils.alert({
title: 'Ein Alert',
body: "Alert Body Text",
onOpen: (modalCtrl) => {
console.log("onOpen => modalCtrl", modalCtrl);
}
}).then(function (result) {
console.log("Alert Result", result);
});
}
Developing the Library
Während der Entwicklung an der Library muss diese getestet werden, gebuilded werden sowie gepublished werden können. Hier steht wie's geht:
Testing
Simply run ng serve
inside the root folder. The AppModule
will be served and you're able to consume your library on the fly.
Building & Publishing
To build and publish the library you have to increase the version number inside the package.json
(hint: you will find two package.json
files. You have to increase the version number inside the ./projects/ng-modal/package.json
and not the package.json
inside the root folder!)
After pushing the commit to Gitlab, a Pipeline will start, build and publish your changes.
This automatic publishing will only start, if you increase the version number! If you push your changes without an increased version number nothing else than pushing will happen.