How to make a Modal reusable in Angular 2?

前端 未结 1 424
死守一世寂寞
死守一世寂寞 2020-12-03 15:50

Reusability is very important when programming, and anything we can do to reduce duplication of code is going to help us out.

I have to use Modal popups to display in

相关标签:
1条回答
  • 2020-12-03 16:21

    The best solution so far is to create a custom reusable modal component and modal service in a shared module (where the component and service is exported), so that it can be used in any other module where shared module is imported

    shared.module.ts

    @NgModule({
      imports: [
        CommonModule
      ],
      declarations: [
        ModalComponent,
      ],
      providers:[ 
        ModalService
       ],
      exports:[
        ModalComponent
      ]
    })
    

    modal.component.html

    <div class="custom-modal">
      <div class="model-close-btn">
          <img class="close-image" src="assets/icon/png/close.png" alt="">
      </div>
      <ng-content></ng-content>
    </div>
    

    modal.component.ts

    import { Component, OnInit, OnDestroy, ElementRef, Input } from '@angular/core';
    import { ModalService } from '../services/modal.service';
    import { element } from '@angular/core/src/render3';
    
    @Component({
      selector: 'custom-modal',
      templateUrl: './modal.component.html',
      styleUrls: ['./modal.component.scss']
    })
    export class ModalComponent implements OnInit, OnDestroy {
      @Input() id: string;
      private element: any;
    
      constructor(private modalService: ModalService, private el: ElementRef) {
          this.element = el.nativeElement;
      }
    
      ngOnInit(): void {
          let modal = this;
    
          // ensure id attribute exists
          if (!this.id) {
              console.error('modal must have an id');
              return;
          }
    
          // move element to bottom of page (just before </body>) so it can be displayed above everything else
          document.body.appendChild(this.element);
    
          // close modal on background click
          this.element.addEventListener('click', function (e: any) {
              if (e.target.className === 'modal__overlay modal__overlay--toggle') {
                  modal.close();
              }
          });
    
          this.element.addEventListener('click', function (e: any) {
            if (e.target.className === 'model-close-btn' || e.target.className === 'close-image' ) {
                modal.close();
            }
        });
    
          // add self (this modal instance) to the modal service so it's accessible from controllers
          this.modalService.add(this);
      }
    
      // remove self from modal service when directive is destroyed
      ngOnDestroy(): void {
          this.modalService.remove(this.id);
          this.element.remove();
      }
    
      // open modal
      open(): void {
        //console.log(this.element);
          this.element.style.display = 'block';
    
      }
    
      // close modal
      close(): void {
          this.element.style.display = 'none';
      }
    }
    

    modal.component.scss

    /* MODAL STYLES
    -------------------------------*/
    :host(custom-modal) {
      /* modals are hidden by default */
      display: none;
    
    }
    
    .custom-modal-open {
      /* body overflow is hidden to hide main scrollbar when modal window is open */
      display: block !important;
    }
    
    .model-close-btn {
      position: fixed;
      width: 18px;
      height: 18px;
      right: 50px;
      top: 50px;
      z-index: 9999;
      background-color: #fff;
      border-radius: 50px;
      padding: 10px;
      cursor: pointer;
    
      img {
        width: 18px;
      }
    }
    

    modal.service.ts

    import { Injectable } from '@angular/core';
    
    @Injectable({
      providedIn: 'root'
    })
    export class ModalService {
    
      private modals: any[] = [];
    
      constructor() { }
    
      add(modal: any) {
        // add modal to array of active modals
        this.modals.push(modal);
      }
    
      remove(id: string) {
        // remove modal from array of active modals
        this.modals = this.modals.filter(x => x.id !== id);
      }
    
      open(id: string) {
        // open modal specified by id
        let modal: any = this.modals.filter(x => x.id === id)[0];
        modal.open();
      }
    
      close(id: string) {
        // close modal specified by id
        let modal: any = this.modals.filter(x => x.id === id)[0];
        modal.close();
      }
    
    }
    

    Now if you want to use this component in a sample component in another module , do the following:

    Step 1: Import the shared module to the sample module where you want to use the custom-modal

    sample.module.ts

    @NgModule({
      declarations: [
        SampleComponent,
      ],
      imports: [
        SharedModule
      ],
    })
    

    Step 2:

    sample.component.ts

      import { ModalService } from 'src/shared/services/modal.service';
    
    
      constructor(private modalService: ModalService){}
    
      //  call this function to open modal by passing modal id
      openModal(id: string) {
        this.modalService.open(id);
      }
    
      // just call this function to close modal by passing modal id
      closeModal(id: string) {
          this.modalService.close(id); 
      }
    

    sample.component.html

    <!-- modal popup started -->
      <custom-modal id="custom-modal-one">
    
       // add your any custom modal template code here and logic in sample.component.ts
    
      </custom-modal>
    <!-- modalp popup ends -->
    
    0 讨论(0)
提交回复
热议问题