npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ngx-modalable

v1.0.5

Published

ngx-modalable enable displaying a component template or a portion of it in a modal while preserving the binding. <br/>

Downloads

10

Readme

ngx-modalable enable displaying a component template or a portion of it in a modal while preserving the binding.

(Click the animated gif below to enlarge it)

This is useful for cases where the component size is smaller than its content size (e.g. card), and you want to comfortably view/edit that content in a modal instead of scrolling inside the component.

In case you edit the component, the data binding remains when the template is displayed in the modal.

you can display in a modal the entire component template OR a portion of it. For example, if your template contains a form and you wish to display only the form portion in a modal.

To play locally the sample displayed above, clone this repo and run 'npm install' and 'ng serve tester'.

Using ngx-modalable

Wrap the template portion you want to display in a modal with ngx-modalable tag. In the example below the template portion contains a material card.

card.component.ts

export class CardComponent {
  isExpanded = false;
  modalRef;

  constructor(public modalService: MatDialog) {}

  onClickToggle() {
    this.isExpanded = !this.isExpanded;
  }

  onClickTest() {
    alert('click event was captured in the card component class!');
  }

  openModal(templateRef: TemplateRef<any>) {
    this.modalRef = this.modalService.open(templateRef, { disableClose: true });
  }

  closeModal() {
    this.modalRef.close();
    this.modalRef = null;
  }
}

card.component.html

<ngx-modalable
    [isExpanded]="isExpanded"
    [openFn]="openModal.bind(this)"
    [closeFn]="closeModal.bind(this)">
  <mat-card class="content" [ngClass]="{shadowless: isExpanded}">
    <mat-card-header>
      <mat-card-title>CARD TITLE</mat-card-title>
      <button mat-button mat-raised-button (click)="onClickToggle()">{{isExpanded ? 'Collapse' : 'Expand'}}</button>
    </mat-card-header>
    <mat-card-content>
      <mat-form-field appearance="fill"  class="textarea">
        <mat-label>Textarea</mat-label>
        <textarea matInput></textarea>
      </mat-form-field>
    </mat-card-content>
    <mat-card-actions>
      <button mat-button mat-raised-button color="primary" (click)="onClickTest()">TEST CLICK BINDING</button>
    </mat-card-actions>
  </mat-card>
</ngx-modalable>

The template in initially displayed inline, it is determined by the value of 'isExpanded' which defaults to false.

The tag ngx-modalable receives 3 input fields:

  1. isExpanded - a boolean which determines if the template should be displayed in a modal or not.
  2. openFn - a function that will be called by ngx-modalable when isExpanded changes to true. the function will be passed a parameter of type TemplateRef which represents the template portion to be displayed in a modal. the function should use this parameter to display the template in a modal. opening the modal from the containing component and not by ngx-modalable makes it flexible to use any theming framework such as material, bootstrap, prime, ng-zoro, nebular, etc.
  3. closeFn - a function that will be called by ngx-modalable when isExpanded changes to false. the function should close the modal, the template portion will return to be displayed inline.

Installation

npm install ngx-modalable

Import ngx-module in your shared module.

shared.module.ts

import { NgxModalableModule } from 'ngx-modalable';
.
.
@NgModule(
  imports: [
    NgxModalableModule
  ]
})
export class SharedModule {}

Styling

Sometimes you would want to style your template when it is displayed in a modal, for example if you want to drop the card shadow.Then you could have a class or style which depends on 'isExpanded' property: <mat-card class="content" [ngClass]="{shadowless: isExpanded}">

and in you card.component.scss:

.shadowless {
  box-shadow: none;
}

Enabling modal close by pressing ESC key or by clicking the backdrop

The above code shown for the card class is appropriate for modals which cannot be closed by pressing ESC or by clicking the backdrop. In case you want to allow it then your component class will change a bit:

card.component.ts

export class Card {
  isExpanded = false;
  modalRef;

  constructor(public modalService: MatDialog) {}

  onClickToggle() {
    this.isExpanded = !this.isExpanded;
  }

  onClickTest() {
    alert('click event was captured in the card component class!');
  }

  openModal(templateRef: TemplateRef<any>) {
    this.modalRef = this.modalService.open(templateRef, { disableClose: false });
    this.modalRef.afterClosed().pipe(take(1)).subscribe(() => {
      if (this.isExpanded) this.onClickToggle();
    });
  }

  closeModal() {
    this.modalRef.close();
    this.modalRef = null;
  }
}

Wrapper component

If you use ngx-modalable in several components, then you will have a repeated code of opening and closing the modal in all the consuming components. It would be better to make a wrapper component, place the code that handles the modal within it and use the wrapper component by all the consuming components. Below is a wrapper component example named AppModalable.

app-modalable.component.ts

export class AppModalableComponent {
  @Input() isExpanded = false;
  modalRef;

  constructor(public modalService: MatDialog) {}

  openModal(templateRef: TemplateRef<any>) {
    this.modalRef = this.modalService.open(templateRef, { disableClose: true });
  }

  closeModal() {
    this.modalRef.close();
    this.modalRef = null;
  }
}

app-modalable.component.html

<ngx-modalable
    [isExpanded]="isExpanded"
    [openFn]="openModal.bind(this)"
    [closeFn]="closeModal.bind(this)">
  <ng-content></ng-content>
</ngx-modalable>

The card component code will be reduced when using app-modalable.

card.component.ts

export class Card {
  @Input() isExpanded = false;
    
  onClickToggle() {
    this.isExpanded = !this.isExpanded;
  }
    
  onClickTest() {
    alert('click event was captured in the card component class!');
  }
}

card.component.html

<app-modalable [isExpanded]="isExpanded">
  .
  CARD CONTENT HERE
  .
</app-modalable>