How to display simple modal with ng-bootstrap (Angular 2) - javascript

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>

Related

Get Value from a Input field Angular With Code

I want to take values from input to a function to alert
here is my html
<div class="container p-5 ">
<input #titleInput *ngIf="isClicked" type="text" class="col-4"><br>
<button (click)="OnClick()" class="btn btn-primary col-2 ">
Show
</button>
<button (click)="Send(titleInput.value)" class="btn btn-success col-2 m-3">
Send
</button>
</div>
and here is my componet.ts
import { Component} from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
Send(data: any) {
alert(data)
}
OnClick() {
this.isClicked=true;
}
title = 'demoproject1';
isClicked=false;
}
I want to get value from input field and I want get value into components function
Create Variable to store input value:
component.ts
...
export class AppComponent {
input: string;
...
Add FormsModule to your module.ts if not already imported
module.ts
import { FormsModule } from '#angular/forms';
setup ngModel on your HTML:
html:
<input type="text" [(ngModel)]="input" ></-input>
Important:
Dont forget to add a Route to the component in your app-routing.module.ts
ngModel Docs
#ViewChild('titleInput') titleInput:
ElementRef;
ngAfterViewInit() {
// Put your logic here ...
}
i put the code here :
https://stackblitz.com/edit/angular-ivy-b4hcqw?file=src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fapp.component.html

Detect Click event inside ngx bootstrap modal

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

Angular 6 modal opening on same page not in popup

I am have an angular 6 project that includes a toolbar on the top of the page with a "Sign In" button. When I click on this button, I want a modal dialog to appear.
However, I ran there are two issues illustrated in the screenshot below. The first is when I load the page, both modals (outlined in red) are loaded. They should only appear if the appropriate button is clicked.
Stackblitz project is at below link:
https://stackblitz.com/github/eugene01a/online-exam/tree/master/frontend
The second issue is why are they not appearing in their own dialog popup?
import {
Component,
OnInit
} from '#angular/core';
import {
ModalService
} from "./_services";
import './_content/app.less';
import './_content/modal.less';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent implements OnInit {
authenticated = false;
constructor(private modalService: ModalService) {}
ngOnInit() {}
openModal(id: string) {
this.modalService.open(id);
}
closeModal(id: string) {
this.modalService.close(id);
}
}
<!-- main app container -->
<mat-toolbar color="primary" class="mat-elevation-z10">
<button mat-button>Online Exams</button>
<button mat-button>About</button>
<!-- This fills the remaining space of the current row -->
<span class="fill-remaining-space"></span>
<button mat-button (click)="openModal('signin-modal')" *ngIf="!authenticated">Sign In</button>
<button mat-button (click)="openModal('signout-modal')" *ngIf="authenticated">Sign Out</button>
</mat-toolbar>
<div class="view-container">
<router-outlet></router-outlet>
</div>
<jw-modal id="signin-modal">
<h1>Sign in button clicked</h1>
<button (click)="closeModal('signin-modal');">Close</button>
</jw-modal>
<jw-modal id="signout-modal">
<h1>Sign Out button clicked</h1>
<button (click)="closeModal('signout-modal');">Close</button>
</jw-modal>

Modal doesn't appear correctly angular 4

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);
}

Ng-bootstrap modal not showing

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);
}

Categories