DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for NG Bootstrap Modal With Full Typing (ngx-bootstrap-typed-modal)
Urbain Corentin
Urbain Corentin

Posted on

NG Bootstrap Modal With Full Typing (ngx-bootstrap-typed-modal)

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:


Setup

Get the library (ngx-bootstrap-typed-modal)

1. Add ngx-bootstrap-typed-modal to package.json

npm i ngx-bootstrap-typed-modal
Enter fullscreen mode Exit fullscreen mode

This will add the following line to the "dependencies" section of the app package.json file:

"dependencies": {
  ...
  "ngx-bootstrap-typed-modal": "^0.5.2"
}
Enter fullscreen mode Exit fullscreen mode

So the package.json will look something like this:

Preview of package.json after library installation

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'
Enter fullscreen mode Exit fullscreen mode

Then in the imports section add:

imports: [
  ...
  NgbTypedModalModule
],
Enter fullscreen mode Exit fullscreen mode

The app.module should look something like this:
Preview of the module.app after adding the import

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.

Preview of the final result of a typed modal

Create the component

Let's starting by adding the component that will hold your modal content and behavior:

ng generate component matrix-modal
Enter fullscreen mode Exit fullscreen mode

And go into the matrix-modal/matrix-modal.component.ts, it should look like this:
Preview of the matrix-modal.component.ts

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';
Enter fullscreen mode Exit fullscreen mode

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();
  }
}
Enter fullscreen mode Exit fullscreen mode

The component should be like this:
Preview of the matrix-modal.component.ts after extending

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>
Enter fullscreen mode Exit fullscreen mode

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');
  }
Enter fullscreen mode Exit fullscreen mode

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!

Demo of a Typescript error for the output

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 πŸ‡')
    })
  }
Enter fullscreen mode Exit fullscreen mode

And...
Demo of typing in the modal result

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)

Create an Account!
Now it's your turn!
Β 
πŸ—’ Share a tutorial
πŸ€” Reflect on your coding journey
❓ Ask a question

Create an account to join hundreds of thousands of DEV members on their journey.