I am using ng-bootstrap Here try to do a modal sample ,but when i click on open modal it doesn't appear although it exists inside the DOM.
my angular core version :4.0.0 , #ng-bootstrap/ng-bootstrap :1.0.0-alpha.29, bootstrap :3.3.7
test-modal.component.html
<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">×</span>
</button>
</div>
<div class="modal-body">
<p>Hello, {{name}}!</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="activeModal.close('Close click')">Close</button>
</div>
test-modal.component.ts
import {Component,Input} from '#angular/core';
import {NgbModal,NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-test-modal',
templateUrl: './test-modal.component.html',
styleUrls: ['./test-modal.component.css']
})
export class TestModalComponent {
#Input() name;
constructor(public activeModal: NgbActiveModal) {}
}
the open function in app.component.ts with the constructor
constructor(private modalService: NgbModal) {}
open() {
const modalRef = this.modalService.open(TestModalComponent);
}
the button inside app.component.html
<button class="btn btn-lg btn-outline-primary" (click)="open()">Launch demo modal</button>
I think the problem might be your bootstrap version bootstrap :3.3.7, when I got to the homepage it says it is for Bootstrap 4 (it also says bootstrap 4 on the get started).
And testing over here in a Angular 4 + Bootstrap 4 project I got it working
In package.json
"#ng-bootstrap/ng-bootstrap": "^1.0.0-alpha.29",
"bootstrap": "^4.0.0-alpha.6",
In my module
imports: [
NgbModule.forRoot(), ...
],
entryComponents: [ModalTemplateComponent],
In a component:
modal: NgbModalRef;
constructor(private modalService: NgbModal) { }
async open() {
this.modal = this.modalService.open(ModalTemplateComponent);
const result = await this.modal.result;
console.log(result);
}
Related
I want to open the modal from my typescript code, that is when the component loads on the ngOnit() the modal popup should open , I don't want to create a button on the html file.
HTML:
<button class="btn btn-outline-primary mb-2 mr-2" (click)="openSm(content)">Small modal</button>
<ng-template #content let-modal>
<div class="modal-header">
<h4 class="modal-title">Modal title</h4>
<button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light" (click)="modal.close('Close click')">Close</button>
</div>
</ng-template>
Ts:
openSm(content) {
this.modalService.open(content, { size: 'sm' });
}
stackblitz link
I want to open the modal on ngOnit() function.
just use ViewChild to get the "content" and in ngOnInit call to this.open(this.content)
#ViewChild("content",{static:true}) content:ElementRef;
constructor(private modalService: NgbModal) {}
ngOnInit()
{
this.openSm(this.content)
}
your forked stackblitz
NOTE: I use {static:true} and put the code in ngOnInit because I imagine your "content" is always "visible", else you need use ngAfterViewInit
You can use viewchild and afterviewinit lifehook.
#ViewChild("content") modalContent: TemplateRef<any>;
constructor(private modalService: NgbModal) {}
ngAfterViewInit(): void {
this.modalService.open(this.modalContent, { size: 'sm' });
}
I've created a component with the content of a modal that I want to display on other multiple components.
modal.component.html:
<div class="modal-header">
<h4 class="modal-title"></h4>
<button type="button" class="close" aria-label="Close" (click)="dismissModal()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">...</div>
modal.component.js:
export class ModalComponent implements OnInit {
constructor(
private modal: NgbActiveModal
) { }
dismissModal() {
this.modal.dismiss();
}
}
And I'm calling this content in other parts of my site, such us:
header.component.html:
<button (click)="openModal(myModal)">
Open Modal
</button>
<ng-template #myModal let-modal>
<app-modal-content></app-modal-content>
</ng-template>
header.component.ts:
openModal(content: string) {
this.modalRef = this.modalService.openModal(content, { centered: true });
}
The modal shows up correctly, but when I try to dismiss the modal by pressing X it does not work, because the modal reference is in the header component. How could I dismiss the modal if I'm opening it from other component?
The modal.component.ts file should inject the NgbActiveModal service in order to close the modal.
In the modal.component.ts file constructor:-
import { NgbActiveModal, NgbModal } from '#ng-bootstrap/ng-bootstrap';
export class ModalComponent {
constructor(public modal: NgbActiveModal) {}
}
I have implemented a ngx bootstrap modal following this guide - https://valor-software.com/ngx-bootstrap/#/modals#bs-modal-service. but when the modal is opened how can i detect any click events inside the modal body. I have the below code in my app component.
I have tried this with viewChild but when I am clicking inside the modal after it is opened always returns undefined.
App Component HTML -
<button type="button" class="btn btn-primary" (click)="openModal(template)">Create template modal</button>
<ng-template #template>
<div class="modal-header">
<h4 class="modal-title pull-left">Modal</h4>
<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef.hide()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" #modalBody>
This is a modal.
</div>
</ng-template>
App Component ts -
import { Component, TemplateRef, OnInit, ViewChild, ElementRef } from '#angular/core';
import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
host: {
'(document:click)': 'closemodal($event)'
}
})
export class AppComponent mplements OnInit{
#ViewChild('modalBody', { static : false}) modalBody : ElementRef;
modalRef: BsModalRef;
constructor(private modalService: BsModalService) {}
ngOnInit() {}
openModal(template: TemplateRef<any>) {
this.modalRef = this.modalService.show(template);
}
closemodal(event : any) {
if (!this.modalBody.nativeElement.contains(event.target)){
console.log('clicked in the modal')
}
}
}
I am not sure what is the issue with binding a event handler directly in the modal body DOM. Try the following
Template
<button style="margin: 10px" type="button" class="btn btn-success" (click)="openModal(template)">Create template modal</button>
<ng-template #template>
<div class="modal-header">
<h4 class="modal-title pull-left">Modal</h4>
<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef.hide()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<span style="cursor: pointer" (mouseup)="textClick($event)">Some sample text</span>
<br><br>
<button type="button" class="btn btn-primary" (click)="onClick($event)">Click me</button>
</div>
</ng-template>
Controller
export class AppComponent {
modalRef: BsModalRef;
constructor(private modalService: BsModalService) {}
openModal(template: TemplateRef<any>) {
this.modalRef = this.modalService.show(template);
}
textClick(event: any) {
console.log('text clicked inside modal body');
}
onClick(event: any) {
console.log('button clicked inside modal body');
}
}
Working example: Stackblitz
I'm trying to show a simple Modal with Ng2-bootstrap as per the following page: https://ng-bootstrap.github.io/#/components/modal
However I am getting errors such as:
Error in ./AppComponent class AppComponent - inline template:7:0 caused by: Missing modal container, add <template ngbModalContainer></template> to one of your application templates.
ORIGINAL EXCEPTION: Missing modal container, add <template ngbModalContainer></template> to one of your application templates.
What am I doing wrong? I've got the following code to try and make this work:
Index.html:
<body>
<app-root>Loading...</app-root>
<template ngbModalContainer></template>
</body>
app.module.ts:
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
...
#NgModule({...
imports: [
BrowserModule,
FormsModule,
HttpModule,
NgbModule.forRoot() ...
app.component.ts:
import { NgbModal, NgbActiveModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
import { SasModalComponent } from './sas-modal/sas-modal.component';
...
constructor(..., private modalService: NgbModal){
}
...
open() {
console.log("trying to open");
const modalRef = this.modalService.open(SasModalComponent);
}
app.component.html
<button class="btn btn-lg btn-outline-primary" (click)="open(content)">Launch demo modal</button>
sas-modal.component.ts
import { NgbModal, NgbActiveModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
...
#Component({
selector: 'sas-modal',
templateUrl: './sas-modal.component.html',
styleUrls: ['./sas-modal.component.css']
})
export class SasModalComponent {
closeResult: string;
constructor(private modalService: NgbModal) {}
open(content) {
this.modalService.open(content);
}
}
sas-modal.component.html:
<template #content let-c="close" let-d="dismiss">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="c('Close click')">Close</button>
</div>
</template>
sas-component.ts should be : -
import { NgbModal, NgbActiveModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
...
#Component({
selector: 'sas-modal',
templateUrl: './sas-modal.component.html',
styleUrls: ['./sas-modal.component.css']
})
export class SasModalComponent {
closeResult: string;
constructor(private activeModal: NgbActiveModal) {}
}
app.module.ts Should contain SasModuleComponent in the declaration array and a
entryComponent field that contains SasModuleComponent : -
#NgModule({
imports: [ BrowserModule,
FormsModule , HttpModule, NgbModule.forRoot()],
declarations: [ AppComponent, SasModalComponent],
bootstrap: [ AppComponent ],
entryComponents: [SasModalComponent]
})
You need a entryComponent field in #NgModule()in your module file because you are loading the SasModuleComponent dynamically here this.modalService.open(SasModalComponent).
Try adding <template ngbModalContainer></template> in app-root template
Example:
#Component({
selector: 'app-root',
template: '<template ngbModalContainer></template>'
})
saurav1405's answer provided me with enough useful information to figure this out, however his solution didn't 100% work for me.
For this reason I've upvoted saurav1405's response, but couldn't claim is as the answer as I've had to do a bit more to get it to work for me.
The main difference was having a seperate control component and content component.
This is how I got it working:
>> app.module.ts
Note: saurav1405 suggested putting ModalContentComponent into declarations, (possibly a typo after reviewing his comments again).
but you need to put the actual modal custom modal components in here (in this case SasModalComponent & SasModalContent).
And the content component (SasModalContent) needs to be the entry component.
import { SasModalComponent, SasModalContent } from './sas-modal/sas-modal.component';
...
#NgModule({
declarations: [
AppComponent,
SasModalComponent,
SasModalContent
],
entryComponents: [SasModalContent],
...
>> app.component.html:
The ngbModalContainer declaration should be along side the component declaration in the parent component html template, not in the index.html, which I think was the main reason I was getting the errors posted in the question.
<template ngbModalContainer></template>
<sas-modal-component></sas-modal-component>
>> sas-modal.component.ts:
This file combines both the control component [sas-modal-component] (that opens the content / template) and the content component [sas-modal-content] (that has the reference to the active modal and modal template).
import {Component, Input, Compiler } from '#angular/core';
import {NgbModal, NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'sas-modal-content',
templateUrl: 'sas-modal-content.html'
})
export class SasModalContent {
#Input() name;
constructor(public activeModal: NgbActiveModal) { }
}
#Component({
selector: 'sas-modal-component',
templateUrl: 'sas-modal.component.html'
})
export class SasModalComponent {
constructor(private modalService: NgbModal, private compiler: Compiler) { }
open() {
//this.compiler.clearCacheFor(SasModalContent); //Only use when the template is caching when you don't want it to.
const modalRef = this.modalService.open(SasModalContent);
modalRef.componentInstance.name = 'World';
}
}
>> sas-modal.component.html: Contains the button / control to open the modal
<h2> Click the button to open the modal</h2>
<button class="btn btn-lg btn-outline-primary" (click)="open()">Launch demo modal</button>
>> sas-modal-content.html: Holds the modal template - can be whatever you want
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Hi there!</h4>
</div>
<div class="modal-body card-info">
<h3 style="color: white;">So nice to meet you</h3>
<h4 style="color: white;">This modal is great!</h4>
</div>
<div class="modal-footer ">
<button type="button" class="btn btn-secondary" (click)="activeModal.close('Close click')">Close</button>
</div>
My goal is to open a modal in angular when I press a button. I decided to use ng-bootstrap for this. I went to their website and decided to copy paste the default modal code into my application.
The button is showing and when I click it, the screen moves a little bit, but there is no modal to be seen. When I click the button a second time I get a feedback Dismissed by clicking on a backdrop. The console shows me no errors.
Does anyone know how to fix this?
image of what the webpage looks like
homepage HTML file: the ng-template is the modal
<div class="col-md-8 col-md-offset-2">
<h5>Welcome to MovieMeter! <span *ngIf="isLoggedIn"> You are logged in as {{fullName}}</span></h5>
<br>
<ng-template #content let-c="close" let-d="dismiss">
<div class="modal-header">
<h4 class="modal-title">Modal title</h4>
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="c('Close click')">Close</button>
</div>
</ng-template>
<button class="btn btn-lg btn-outline-primary" (click)="open(content)">Launch demo modal</button>
<hr>
<pre>{{closeResult}}</pre>
<h3>Trailers:</h3>
<hr>
<ul>
<li *ngFor="let trailer of trailers">
<img src="{{trailer.body.items[0].snippet.thumbnails.high.url}}" alt="nope">
<div class="trailerTitle"><h5>{{trailer.movie.title}}</h5></div>
</li>
</ul>
<app-cinema-featured></app-cinema-featured>
</div>
Home.component.ts
import {Component, OnInit} from "#angular/core";
import {AuthService} from "../auth/auth.service";
import {MovieService} from "../movie/movie.service";
import {NgbModal, ModalDismissReasons} from '#ng-bootstrap/ng-bootstrap';
#Component({
styleUrls: ['./home.component.css'],
selector: 'app-home',
templateUrl: './home.component.html'
})
export class HomeComponent implements OnInit {
isLoggedIn:Boolean;
fullName;
trailers;
closeResult: string;
constructor(private modalService:NgbModal, private authService: AuthService, private movieService: MovieService){}
ngOnInit(){
if (localStorage.getItem('token') !== null || undefined){
this.isLoggedIn = true;
this.fullName = localStorage.getItem('fullName');
}
// get the thumbnails and links of the three most recent movie trailers via the youtube API
this.movieService.getTrailers()
.subscribe(trailers => {
this.trailers = trailers.result;
console.log(this.trailers);
})
}
open(content) {
this.modalService.open(content).result.then((result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
});
}
private getDismissReason(reason: any): string {
if (reason === ModalDismissReasons.ESC) {
return 'by pressing ESC';
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
return 'by clicking on a backdrop';
} else {
return `with: ${reason}`;
}
}
}
Update: this are the elements in the console after I clicked the button. The ng backdrop and ng-modal are showing, but cannot be seen.
After trying a lot of things I discovered that I needed bootstrap 4 instead of bootstrap 3.
Try to use #ViewChild to select the modal in your component code:
HTML
<button class="btn btn-lg btn-outline-primary" (click)="open()">Launch demo modal</button>
TS
#ViewChild("content") content: NgbModal;
open() {
this.modalService.open(this.content).result.then((result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
});
}
//1. The modal component has to be registered in entryComponents (angualr 8 and prev)
entryComponents: [
YourModalComponent
],
providers: [
...]
//2. also the model directly inputted in the open:
openConfirmUpdateModal() {
this.modalService.open( YourModalComponent);
}