11

What I'm trying to do is open a modal from another component, however I keep getting this error TypeError: Cannot create property 'validator' on string 'test1' when component1.html loads because childModal is included. How can I get rid of these errors and implement this properly?

component1.html

<button type="button" class="btn btn-outline-primary btn-lg" (click)="modal.showModal()">Test
......
<child-modal #childModal ></child-modal>

component1.ts

 @ViewChild('childModal') childModal: ModalComponent;

modal.html

<div bsModal #childModal="bs-modal" class="modal fade" tabindex="-1" role="dialog>
    <div class="modal-dialog modal-lg">
      <div class="modal-content">
          <input type="text" formControl="test1">
          <input type="text" formControl="test2">
          </div>
     </div>
</div>   

modal.component.ts

constructor(private modalService: BsModalService) {
    this.form = new FormGroup({
      'test':                     new FormControl(),
      'test2':                    new FormControl()
      }) 
 }
derrickrozay
  • 1,048
  • 3
  • 15
  • 37

3 Answers3

19

If you're trying to open a Modal Component from another Component, then this is the right way to do it with ngx-bootstrap:

import { Component } from '@angular/core';
import { BsModalService } from 'ngx-bootstrap/modal';
import { BsModalRef } from 'ngx-bootstrap/modal/modal-options.class';

/* This is the Component from which we open the Modal Component */
@Component({
  selector: 'my-component',
  templateUrl: './service-component.html'
})
export class MyComponent {
  bsModalRef: BsModalRef;
  constructor(private modalService: BsModalService) {}

  public openModalWithComponent() {
    /* this is how we open a Modal Component from another component */
    this.bsModalRef = this.modalService.show(ModalContentComponent);
  }
}

/* This is the Modal Component */
@Component({
  selector: 'child-modal',
  template: `
    <div class="modal-header">
      <h4 class="modal-title pull-left">Title</h4>
      <button type="button" class="close pull-right" aria-label="Close" (click)="bsModalRef.hide()">
        <span aria-hidden="true">&times;</span>
      </button>
    </div>
    <div class="modal-body">
      ...
    </div>
    <div class="modal-footer">
      <button type="button" class="btn btn-default" (click)="bsModalRef.hide()">Close</button>
    </div>
  `
})
export class ChildModalComponent {
  constructor(public bsModalRef: BsModalRef) {}
}

template of the Component which is calling the Modal:

<button type="button" class="btn btn-primary" (click)="openModalWithComponent()">Create modal with component</button>

So you should NOT include the Modal Component in the template like this:

 <child-modal #childModal ></child-modal>

Official doc:

https://valor-software.com/ngx-bootstrap/#/modals#service-component

Francesco Borzi
  • 56,083
  • 47
  • 179
  • 252
  • How can I call the `openModalWithComponent()` from another components HTML page? Doesnt it have to exist in the same component in order to be able to call it like that? – derrickrozay Oct 12 '17 at 15:03
  • as I showed in my answer, in another component's HTML page you can trigger the execution of a method (in my example the method is `openModalWithComponent()` triggered by clicking a ` – Francesco Borzi Oct 12 '17 at 15:09
  • It doesn't work. I am trying to call `this.bsModalRef = this.modalService.show(ModalComponent);` from my above code and it just shows an overlay but the actual page doesnt show up. In your above example are both the components in different files? Thats how I have it set it up I dont want a single file since I will have 3 different modals – derrickrozay Oct 12 '17 at 20:49
  • 3
    Okay I figured it out. I had to take out the reference to `bsmodal` in child component. The problem now is that after taking out the first line of `modal.html` the modal now opens up as small instead of large. BTW Thank you for your help! – derrickrozay Oct 12 '17 at 21:35
  • @derrickrozay please mark the answer as accepted if it solves your issue. For the other issue, look for or open a separate question – Francesco Borzi Oct 13 '17 at 07:57
  • 1
    I'm getting an error `No component factory found for . Did you add it to @NgModule.entryComponents?`. My code is exactly like how you have it here, what am I doing wrong? – janedoe Aug 05 '18 at 01:28
  • 1
    It looks like there's a typo. There is no 'ModalContentComponent', it should read 'ChildModalComponent'. – Ε Г И І И О Aug 09 '21 at 16:57
3
If you use same component then, 

HTML #
    <button (click)="openModalWithComponent()">open</button>

    // for display purpose
    <ng-template #template>
      <div class="modal-body">
      </div>
    </ng-template>

COMPONENT #
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
import { BsModalService } from 'ngx-bootstrap/modal';
import { ViewChild, ElementRef } from '@angular/core';

      bsModalRef: BsModalRef;
constructor(private modalService: BsModalService) {}
      @ViewChild('template') elementView: ElementRef;
    openModalWithComponent() {    
        this.bsModalRef = this.modalService.show(this.elementView);
        // this.bsModalRef.content.closeBtnName = 'Close';
        // (click)="bsModalRef.hide()"

    }
-2

you only need to add your child-component into the entryComponents in your module like this:

entryComponents: [
    childComponent
]

it works for me

SuperStar518
  • 2,814
  • 2
  • 20
  • 35