1
votes

I am not aware if this is even possible in Angular 2/4. I have a Modal Component which in turn has a Modal Content Component. I also have a service which allows to open/close the modal instance. I am using ngbModal.

The modal Content template needs to show/hide some fields based on the boolean parameter.

My Page component has a button which on click needs to open the modalInstance with the boolean parameter.

Here is what i have,

page.component.html

 <div class="bar-sec">
   <action-bar [options]="btnOpts" (select) = 
      "actionBarSelectHandler($event)">
   </action-bar>
</div>
<div class="grid-sec">
</div>
 **<app-ad-search [userOnly]='userOnly'></app-ad-search>**

page.component.ts

 import {Component, ViewChild} from '@angular/core';
 import { NgbDropdownConfig } from '@ng-bootstrap/ng-bootstrap';
 import { SearchModalComponent} from '../../X/search-modal.component';
 import { SearchContentComponent} from '../../X/search-content.component';
 import { XModalService} from '../../X/x-modal.service';

@Component ({
  selector: 'page-test',
  templateUrl: './page.component.html',
  providers: [XModalService]
})

 export class VCenterMachinesComponent {
   XModalService: XModalService;
   filterText: String = '';
   machines: any[];
   btnOpts: {};
   **userOnly:boolean = true;**

  **@ViewChild(SearchModalComponent) private 
       SearchModalComponent:SearchModalComponent;**

 constructor(E:XModalService) {
  this.XModalService = E;
  **this.userOnly = true;**
 }

 actionBarSelectHandler(data) {
    if (data.item.id === 'assignuser') {
        **this.XModalService.openSearchModal()**.then(() => {
            console.log('close');
        }, () => {
            console.log('dismiss');
        });
     }
  }

 ngOnInit() {
    this.machines = [];
   this.filterText = '';
   this.btnOpts = {
     data: [{
                id: "assignuser",
                label: "Assign User...",
                enabled: true
            }]
   };

  }
 }

search-modal.component.ts

    import { Component, OnInit, OnDestroy, Input } from '@angular/core';
    import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';

    import { SearchContentComponent } from './search-content.component';

        @Component({
            selector: 'app-ad-search',
            template: `
                <modal-header (onClose)="activeModal.dismiss();">
                    <span>{{modalTitle}}</span>
                </atk-modal-header>
                <modal-body>
                    <search-content>
                    </search-content>
                </modal-body>
                <modal-footer [buttons] = "modalBtns" 
      (onClick)="btnClick($event)">
                </modal-footer>
            `
        })
        export class SearchModalComponent{
            @Input()
            private modalBtns: any[] | any = [{
                id: 'ok',
                label: 'OK',
                primary: true,
                disabled: true
            }, {
                id: 'cancel',
                label: 'Cancel',
                primary: true,
                disabled: false
            }];
            @Input()
            **public userOnly:boolean = false;**

            @Input()
            public modalTitle: string = (this.userOnly) ? 'XXX':'YYY';


            constructor(private activeModal: NgbActiveModal) { }

            btnClick(btn) {
                if (btn.id === 'ok') {
                    this.activeModal.close(this.selectedRows);
                } else {
                    this.activeModal.dismiss();
                }
            }


        }

search-content.component.ts

  import { Component, OnInit, OnDestroy, Input, Output, EventEmitter } from 
    '@angular/core';
            @Component({
              selector: 'ad-search-content',
              template: '<div class="form-group row" *ngIf="!userOnly">
                    <label class="col-sm-4 col-form-label">Type:</label>
                    <div class="col-sm-8">
                        <label class="custom-control custom-checkbox">
                            <input type="checkbox" class="custom-control-
       input" [(ngModel)]="filters.type.users" name="usersType">
                        </label>
                    </div>
                </div>
                <div class="form-group row">
                    <label class="col-sm-4 col-form-label">Domian:</label>      
                </div>'
            })
            export class SearchContentComponent implements OnInit, OnDestroy 
        {

                constructor() { }

                ngOnInit() {}
                ngOnDestroy() {}

            }

x-modal.service.ts

        import { Injectable } from '@angular/core';
        import { NgbModal } from '@ng-bootstrap/ng-bootstrap';

        import { SearchModalComponent } from './search-modal.component';


        @Injectable()
        export class XModalService {
            constructor(private modalService: NgbModal) {}

            **openSearchModal() {**
                return this.modalService.open(SearchModalComponent, 
          {backdrop: 'static'}).result;
            }
        }

Here I tried using the opensearchModal() method from the Xmodalservice to open the modal instance with the boolean value set to true in the typescript file. But i dont even see the page . It complains No provider for NgBActiveModal!

Please let me know as to how could i pass teh boolean to the modal instance that i open?

2
use the angular tag - Bowofola

2 Answers

2
votes

I tried something similar with ngbModal and could not get it to work (I'm very new to Angular, so maybe it would work and I just don't know how). What ended up working very well for me was using ngrx/store and ngrx/effects.

Set up the modal content in a dumb view component, with the boolean data that you want to use within the modal passed as Input from the modal smart container component.

Set up an Effect to react to the button click in your page that calls a reducer function to update a piece of your state that is a boolean of your modal visibility.

In your modal content component select your modal visibility from your state, set your ChangeDetectionStrategy to onPush, and then in your template you just need an *ngIf statement testing the modal visibility boolean.

2
votes

Check out this example on the official ng Bootstrap docs:

import { Component, Input } from '@angular/core';
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
  selector: 'ngbd-modal-content',
  template: `
    <div class="modal-header">
      <h4 class="modal-title">Hi there!</h4>
      <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
        <span aria-hidden="true">&times;</span>
      </button>
    </div>
    <div class="modal-body">
      <p>Hello, {{name}}!</p>
    </div>
    <div class="modal-footer">
      <button type="button" class="btn btn-outline-dark" (click)="activeModal.close('Close click')">Close</button>
    </div>
  `
})
export class NgbdModalContent {
  @Input() name;

  constructor(public activeModal: NgbActiveModal) {}
}

@Component({
  selector: 'ngbd-modal-component',
  templateUrl: './modal-component.html'
})
export class NgbdModalComponent {
  constructor(private modalService: NgbModal) {}

  open() {
    const modalRef = this.modalService.open(NgbdModalContent);
    modalRef.componentInstance.name = 'World';
  }
}

Look at the final two statements of the code: you can save the modalRef returned by ModalService.open() and then access @Input()s using modalRef.componentInstance.