Few weeks ago I was working on an Angular project and I tried to implement a simple deletion confirmation modal with ng-bootstrap and I was surprised to see that there is no way to keep the modal input and result typed, you are forced to manage any
types in the modal... I don't want to have to touch any any
😛.
This is why I created a simple Angular library (ngx-bootstrap-typed-modal) that keep typing and provide a simple way to create modals and process its result.
Let's get started!
Demo:
Prerequisites
Before you start, you need:
-
Angular 14 (
ng new my-app
) -
NG Bootstrap 13. (
ng add @ng-bootstrap/ng-bootstrap
)
Setup
Get the library (ngx-bootstrap-typed-modal)
1. Add ngx-bootstrap-typed-modal
to package.json
npm i ngx-bootstrap-typed-modal
This will add the following line to the "dependencies" section of the app package.json
file:
"dependencies": {
...
"ngx-bootstrap-typed-modal": "^0.5.2"
}
So the package.json
will look something like this:
2. Add NgbTypedModalModule
to the app
Before using the library, you need to register it to Angular, to do so start by adding the import in src/app/app.module
:
import { NgbTypedModalModule } from 'ngx-bootstrap-typed-modal'
Then in the imports
section add:
imports: [
...
NgbTypedModalModule
],
The app.module
should look something like this:
Implementation examples:
Let's using it!
We will create a basic modal that will say "This is your last chance Neo" and return if the user has clicked on the "Blue pill" or "Red pill" button.
Create the component
Let's starting by adding the component that will hold your modal content and behavior:
ng generate component matrix-modal
And go into the matrix-modal/matrix-modal.component.ts
, it should look like this:
For now this is a simple component, in the next section we will transform our component to a fully typed modal.
Create Input and Output types
// `InputData` type which will describe what the component needs as input for the modal to be opened.
type InputData = {
name: string
}
// `OutputData` type which will describe what the component needs as output when the modal is closed.
type OutputData = 'blue' | 'red';
Extend the component with NgbTypedModal
extend and pass our InputData
and OutputData
as arguments.
export class MatrixModalComponent extends NgbTypedModal<InputData, OutputData> implements OnInit {
// ...
constructor() {
super();
}
}
The component should be like this:
Add the logic
In the matrix-modal.component.html
add:
<h4>This is your last chance <b>{{ data.name }}</b></h4>
<div class="modal-footer">
<button class="btn btn-danger" (click)="onRedPillClicked()">Red Pill 💊</button>
<button class="btn btn-primary" (click)="onBluePillClicked()">Blue Pill 💊</button>
</div>
And in the matrix-modal.component.ts
add:
// ...
ngOnInit(): void {
// print to the console data that was passed as input.
console.log('input', this.data);
}
onBluePillClicked(): void {
// send the 'blue' value and close the modal.
this.submitData.emit('blue');
}
onRedPillClicked(): void {
// send the 'red' value and close the modal.
this.submitData.emit('red');
}
Learn more about available methods and properties.
You can see that when calling this.submitData.emit
you have a fully typed parameters, if you enter something else than the allowed string in the InputData
, TypeScript will throw us an error!
Now we have a fully configured modal, all we need to do now is implementing it.
And Finally implement the modal
in the app.component.ts
add:
ngOnInit(): void
{
// create the modal
const modalRef = new MatrixModalComponent().make(this.ngModal)
.setComponent(MatrixModalComponent) // component to place in the modal
.setTitle('Matrix') // set the title
.setInput({name: 'Neo'}) // pass inputs
.show() // show the modal
// handle the modal response
modalRef.result.then(result => {
// check that the user has not dismissed the modal
if(!result) {
console.log('I will wait')
return;
}
if(result === 'blue')
console.log('You were the chosen one!')
if(result === 'red')
console.log('Follow me.')
// TS error
if(result === 'green')
console.log('rabbit hole 🐇')
})
}
You now have a fully typed modal, congrats!! 🎉
Thanks for reading the whole story, if you have any improvements feel free to open a pull request!
Top comments (0)