Angular 2 ng2-bootstrap модальный внутри дочернего компонента, вызываемый из родительского компонента

Это сложно объяснить. У меня был простой рабочий модальный пример ng2-bootstrap. Я расширил его, включив в него пример шаблона Boostrap 4 Jumbotron для моей домашней страницы, теперь модальное окно ng2-bootstrap ничего не делает. Я вижу, что this.childModal.show() в дочернем модальном компоненте вызывается при нажатии кнопки, но ничего не происходит. В консоли Chrome нет ошибок и нет модальных окон. Я понятия не имею, что делать дальше: - /

// ============================================================================
// /src/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { ModalModule } from 'ng2-bootstrap/modal';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';

import { AppComponent } from './app.component';
import { DemoModalChildComponent } from './demo-modal-child.component';

@NgModule({
    declarations: [
        AppComponent, DemoModalChildComponent
    ],
    imports: [
        BrowserModule,
        FormsModule,
        HttpModule,
        NgbModule.forRoot(),
        ModalModule.forRoot()
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }


// ============================================================================
// /src/app/app.component.ts

import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    title = 'app works!';
}



<!-- ========================================================================== -->
<!-- /src/app/app.component.html -->

<nav class="navbar navbar-toggleable-md navbar-inverse fixed-top bg-inverse">
    <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault"
        aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
        </button>
        <a class="navbar-brand" href="#">Navbar</a>

        <div class="collapse navbar-collapse" id="navbarsExampleDefault">
            <ul class="navbar-nav mr-auto">
                <li class="nav-item active">
                    <a class="nav-link" href="/home">Home <span class="sr-only">(current)</span></a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" (click)="showLoginModal()">Login</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/members">Players</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/game">Game</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link disabled" href="#">Disabled</a>
                </li>
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="http://example.com" id="dropdown01" data-toggle="dropdown" aria-haspopup="true"
                        aria-expanded="false">Dropdown
                        </a>
                        <div class="dropdown-menu" aria-labelledby="dropdown01">
                            <a class="dropdown-item" href="#">Action</a>
                            <a class="dropdown-item" href="#">Another action</a>
                            <a class="dropdown-item" href="#">Something else here</a>
                        </div>
                </li>
            </ul>
            <form class="form-inline my-2 my-lg-0">
                <input class="form-control mr-sm-2" type="text" placeholder="Search">
                <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
            </form>
        </div>
</nav>

<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
    <div class="container">
        <demo-modal-child #c="child"></demo-modal-child>
        <button type="button" class="btn btn-primary" (click)="c.showChildModal()">Open child modal</button>
        <h1 class="display-3">Hello, world!</h1>
        <p>This is a template for a simple marketing or informational website. It includes a large callout called a jumbotron
            and three supporting pieces of content. Use it as a starting point to create something more unique.</p>
        <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more &raquo;</a></p>
    </div>
</div>
<!-- /jumbotron -->

<div class="container">
    <!-- Example row of columns -->
    <div class="row">
        <div class="col-md-4">
            <h2>Heading</h2>
            <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum
                nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed
                odio dui.
            </p>
            <p><a class="btn btn-secondary" href="#" role="button">View details &raquo;</a></p>
        </div>
        <div class="col-md-4">
            <h2>Heading</h2>
            <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum
                nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed
                odio dui. </p>
            <p><a class="btn btn-secondary" href="#" role="button">View details &raquo;</a></p>
        </div>
        <div class="col-md-4">
            <h2>Heading</h2>
            <p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis
                euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa
                justo sit amet risus.</p>
            <p><a class="btn btn-secondary" href="#" role="button">View details &raquo;</a></p>
        </div>
    </div>

    <hr>

    <footer>
        <p>&copy; burnmarkGames 2017</p>
    </footer>
</div>
<!-- /container -->


// ============================================================================
// /src/app/demo-modal-child.component.ts

import { Component, ViewChild } from '@angular/core';
import { ModalDirective } from 'ng2-bootstrap/modal';

@Component({
    selector: 'demo-modal-child',
    templateUrl: './demo-modal-child.component.html',
    exportAs: 'child'
})
export class DemoModalChildComponent {
    @ViewChild('childModal') public childModal: ModalDirective;

    public showChildModal(): void {
        console.log('DemoModalChildComponent.showChildModal fired!');
        this.childModal.show();
    }

    public hideChildModal(): void {
        this.childModal.hide();
    }
}


<!-- ========================================================================== -->
<!-- /src/app/demo-modal-child.component.html -->

<div bsModal #childModal="bs-modal" class="modal fade" tabindex="-1" role="dialog"
    aria-labelledby="mySmallModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title pull-left">Please login...</h4>
                <button type="button" class="close pull-right" aria-label="Close" (click)="hideChildModal()">
          <span aria-hidden="true">&times;</span>
        </button>
            </div>
            <div class="modal-body">
                I am a child modal, opened from parent component!
            </div>
        </div>
    </div>
</div>

person Locohost    schedule 25.02.2017    source источник
comment
вы вызываете modal.show () в своем дочернем компоненте. какой у вас родительский компонент?   -  person Aravind    schedule 25.02.2017
comment
@Aravind В середине app.component.html (<button type="button" class="btn btn-primary" (click)="c.showChildModal()">Open child modal</button>) находится html / code, который вызывает childModal show (). Спасибо за любую помощь, мой друг :-)   -  person Locohost    schedule 25.02.2017
comment
@Aravind Я бы не ответил на ваш вопрос: app.component.ts - родитель.   -  person Locohost    schedule 26.02.2017
comment
Привет, чувак, посмотри на мой ответ ниже ... дай мне знать, если тебе что-то еще нужно   -  person Aravind    schedule 26.02.2017
comment
@Aravind Спасибо за пример! Я изучил код в плункере. Это мое предположение прямо сейчас, пожалуйста, поправьте меня, если я ошибаюсь: у меня есть несколько разных модальных окон, которые должны быть отдельными компонентами, чтобы их можно было использовать в нескольких разных родительских компонентах. Я не думаю, что этот код поддерживает это, так как мне пришлось бы каким-то образом поместить все разные шаблоны в шаблон AppComponent. Я правильно думаю? :-)   -  person Locohost    schedule 26.02.2017
comment
вы можете использовать мой код в качестве универсального модального окна и добавлять разные модальные тела для разных компонентов. Я ясно объяснил в двух последних строках.   -  person Aravind    schedule 26.02.2017
comment
вам нужно еще немного улучшить ответ?   -  person Aravind    schedule 27.02.2017
comment
@Aravind Если бы AppComponent ниже был, скажем, LoginModalComponent, как это изменило бы код? Мне нужно использовать дочерние модальные окна в родительском элементе HomeComponent.   -  person Locohost    schedule 27.02.2017
comment
Да, точно. Имейте свой общемодальный компонент отдельно. Повторно используйте его в модальном компоненте входа в систему. Создайте домашний компонент, который будет иметь модальный вход в качестве дочернего элемента.   -  person Aravind    schedule 27.02.2017
comment
мой ответ решил ваше требование? или нужна дополнительная помощь   -  person Aravind    schedule 27.02.2017
comment
@Aravind Да, ваш совет очень помог. Спасибо, Аравинд! :-)   -  person Locohost    schedule 01.03.2017


Ответы (1)


Ваш общий дочерний модальный компонент будет таким, как показано ниже

import {Component,Input, ViewChild} from '@angular/core';
import { ModalDirective } from 'ng2-bootstrap/ng2-bootstrap';

@Component({
  selector: 'common-modal',
  template: `
   <div bsModal #childModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
  <div class="modal-dialog modal-sm">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title pull-left">{{title}}</h4>
        <button type="button" class="close pull-right" aria-label="Close" (click)="hideChildModal()">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <ng-content select=".modal-body"> </ng-content>
      </div>

      <div class="modal-footer">
        <div class="pull-left">
          <button class="btn btn-default" (click)="hide()"> Cancel </button>
        </div>
      </div>
    </div>
  </div>
</div>
  `,
})
export class CommonModalComponent {
   @ViewChild('childModal') public childModal:ModalDirective;
   @Input() title:string;
  constructor() {
  }
  show(){
    this.childModal.show();
  }
  hide(){
    this.childModal.hide();
  }
}

Использование дочернего компонента в родительском компоненте будет выглядеть, как показано ниже.

import {Component, ViewChild, NgModule,ViewContainerRef} from '@angular/core'
import { BrowserModule } from '@angular/platform-browser';
import { ModalDirective,ModalModule } from 'ng2-bootstrap/ng2-bootstrap';
import {CommonModalComponent} from './child.modal';
@Component({
  selector: 'my-app',
  template: `
    <button type="button" class="btn btn-primary" (click)="childModal.show()">Open modal</button>
    <common-modal  #childModal [title]="'common modal'"> 
    <div class="modal-body">
    Hi heloo </div>
    </common-modal> 

  `,
})
export class AppComponent {
  @ViewChild('childModal') childModal :CommonModalComponent;
  constructor(private viewContainerRef: ViewContainerRef) {
  }

}

Используя приведенный выше код, вы можете создать отдельный общий модальный диалог, который можно использовать повторно, так что ваш верхний и нижний колонтитулы останутся такими же, и вы можете использовать Content-Projection для изменения тела модального диалога.

Живая демонстрация

person Aravind    schedule 26.02.2017