Angular v2.2 broke our get root view component ref hack
temporary workaround:
ComponentsHelper to AppModule (root module)import {ComponentsHelper} from 'ng2-bootstrap/ng2-bootstrap'
// ...
providers: [{provide: ComponentsHelper, useClass: ComponentsHelper}],
AppComponent (root component) public constructor(componentsHelper:ComponentsHelper, vcr:ViewContainerRef) {
componentsHelper.setRootViewContainerRef(vcr);
}
I am facing an issue with my ng2-bootstrap modals. For some reason, I am not able to show them.
Here is my HTML :
<button (click)="testModal.show()">Show this modal</button>
<div bsModal
#testModal="bs-modal"
class="modal fade"
tabindex="-1"
role="dialog"
aria-hidden="true">
<div class="modal-dialog modal-md">
<div class="modal-content">
<div class="modal-body">
TEST
</div>
</div>
</div>
</div>
Here is my NgModule:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { MODAL_DIRECTIVES } from 'ng2-bootstrap/ng2-bootstrap';
@NgModule({
declarations: [ MODAL_DIRECTIVES],
exports: [ MODAL_DIRECTIVES],
imports: [ BrowserModule,
FormsModule,
HttpModule ],
})
export class SharedModule {}
I see this error in the log console :
Error: Uncaught (in promise): Token must be defined!
and the modal does not show up
I am running Angular 2 RC5.
Is there something I am missing here?
Forget about directives, use exported modules
We need to update docs... fast ;(
Thanks for your help, I am now running [email protected].
So I now have a shared module which contains all of the bootstrap modules I am using in the app.
Here is my shared.module.ts:
mport { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';
// Bootstrap modules
import { ButtonsModule, ModalModule, CollapseModule, AccordionModule } from 'ng2-bootstrap/ng2-bootstrap';
@NgModule({
exports: [ ButtonsModule,
CollapseModule,
AccordionModule,
ModalModule ],
imports: [ BrowserModule,
FormsModule,
HttpModule,
RouterModule,
ButtonsModule,
CollapseModule,
AccordionModule,
ModalModule ],
})
export class SharedModule {}
Here is my app.module.ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';
import { routing } from './app.routes';
import { SharedModule } from './shared/shared.module';
@NgModule({
imports: [ BrowserModule,
RouterModule,
FormsModule,
HttpModule,
SharedModule,
routing ],
bootstrap: [ AppComponent ],
})
export class AppModule {}
For some reason, the error "Token must be defined" still shows up when trying to show a modal and I am not using directives anymore.
@escarabin is this still an issue in v1.1.5?
No reaction -> close...
Really sorry about that. I just updated to v1.1.5 and the error has changed to "Cannot read property 'instance' of undefined"
Here is a full screenshot of the log:

I hope it is not too late to request some help on this...
Can you please provide the current HTML-Template, the related component and your ngModule code?
http://bit.ly/ng2-bootstrap-plnkr
Here is plunkr, use it to reproduce issue
I don't get it. It is working in my Plunkr... https://plnkr.co/edit/qFzk0ysRQwbg7vvrkN44?p=preview I am going to investigate more into my code and get back to you if I find any solution.
I updated to v1.1.6 tough. The error has now changed to "applicationRef instance not found" when I try to open a modal.
How do you bootstrap your application?
I have a boot.ts file that looks like this:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
And it is loaded by systemJS inside my HTML head tag :
<script src="systemjs.config.js"></script>
<script>
System.config({
"defaultJSExtensions": true,
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('js/typescript/boot')
.then(null, console.error.bind(console));
</script>
can you try to import ng2 bs like this: https://github.com/valor-software/angular2-quickstart/blob/master/index.html#L16
and compare your system.js config to sample one?
I just tried what you suggest and and got same result.
Actually I also tried to show up a modal inside components of my app.module.ts and it worked. The issue seems to happen only inside component of child modules. In all of my child modules.
sorry, but without reproduce sample, I will not be able to help you :(
In other systemjs issues the problem was: format: 'register',can you try to remove it?
@escarabin is your problem solved? Can I close this issue?
Sorry but it is not solved actually. I will be working on a fix today and will let you know if I find something, it might be useful for others.
Just wanted to verify https://github.com/escarabin. Facing a similar error message with ng2-bootstrap version 1.1.12 the moment I try to invoke:
someModal.show();
Error in some.component.html caused by: ApplicationRef instance not found
export class SomeComponent {
@ViewChild('someModal') public someModal: ModalDirective;
public show():void { this.someModal.show(); }
public hide():void { this.someModal.hide(); }
}
Works fine when loaded in the browser, but fails when executed in a test run by karma. The interesting thing is: Running the following while testing does not lead to any errors:
someModal.hide();
I'm sure I miss something for karma.conf.js or karma.shim.js but I do not have any idea what it could be.
Hey @JFMueller!
Feels good not be alone on that ship. Actually I am facing this error on both Safari, Chrome & Firefox browsers. I am using someModal.show(); in my HTML though
But I also confirm that I am not encountering any issues with using someModal.hide();.
I will try to include someModal.show(); in a typescript function to see if it could be a solution for me but this would still be a workaround.
EDIT : I am using v1.1.6 though. I don't think you should be using ModalDirective anymore.
EDIT : After some testing, I am getting the same error when launching this.someModal.show(); inside a typescript function of my component
@JFMueller I am using v1.1.14 and getting the same error(ApplicationRef instance not found) as you are getting, while testing. Everything works fine in browser though. Where you able to find out a solution?
Hi,
I am also seeing the same issue. It seems to be a timing issue. When I do the following:
import { Component, ViewContainerRef, AfterViewInit, ViewChild } from '@angular/core';
import { LoginModalComponent } from './login-modal/login-modal.component';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit {
private viewContainerRef: ViewContainerRef;
@ViewChild(LoginModalComponent)
public loginModal: LoginModalComponent;
title = 'Hello World!';
public constructor(viewContainerRef: ViewContainerRef) {
this.viewContainerRef = viewContainerRef;
}
public ngAfterViewInit() {
this.loginModal.modal.show();
}
}
Then I get the below error:
error_handler.js:53 Error: ApplicationRef instance not found
at ComponentsHelper.getRootViewContainerRef (components-helper.service.js:50)
at ComponentsHelper.appendNextToRoot (components-helper.service.js:94)
at ModalDirective.showBackdrop (modal.component.js:191)
at ModalDirective.show (modal.component.js:108)
at AppComponent.ngAfterViewInit (app.component.ts:22)
at _View_AppComponent_Host0.detectChangesInternal (host.ngfactory.js:36)
at _View_AppComponent_Host0.AppView.detectChanges (view.js:219)
at _View_AppComponent_Host0.DebugAppView.detectChanges (view.js:324)
at ViewRef_.detectChanges (view_ref.js:130)
at application_ref.js:437
It seems that there are no components registered in this.applicationRef.components at this stage, which is why the above error occurs.. Moving the this.loginModal.modal.show(); into a click directive, then it works fine..
I have the above issue (applicationref instance not found); but mine is triggered from a click function.
seesm like angular 2.2.0 is doing something different from 2.1.2.
ng2 v2.2 added a breaking change to internals working on it
Have this issue too when upgrading to ng2.2, any workaround we can use for the moment?
Ok, for those interested, you can always roll back of course,
I changed:
node_modulesng2-bootstrapcomponentsmodalmodal.component.js
Changed:
//original:
//if (this._isShown && this.config.backdrop) {
if (this._isShown && this.config.backdrop && false) {
to have a temp workaround.
description of temporary workaround added to topic
https://github.com/valor-software/ng2-bootstrap/issues/986#issue-177218652
When I try the temporary workaround I get
(index):36 Error: (SystemJS) Can't resolve all parameters for AppComponent: (?, ViewContainerRef).
Error: Can't resolve all parameters for AppComponent: (?, ViewContainerRef)
......
Use angular-cli with webpack
System js is always a problem
@valorkin is there any reason not to make a <modal-outlet></modal-outlet> like the angular router does? This will be really clear to everybody and you would stop calling it _the hack_ because it is just how angular does it.
Then it is a component where all the modals (or at least the backdrop) can be rendered in isolated environment. Everybody is happy and it won't ever be a problem again.
e.g. app component template would be similar to
<header>/<header>
<router-outlet>/<router-outlet>
<footer>/<footer>
<modal-outlet>/<modal-outlet>
Maybe the same could be applied for the tooltips
I agree wtih @smnbbrv. The outlet approach seems much more robust.
Having core functionality depend on brittle hacks really shakes my confidence in the whole framework. The workaround suggested is also not working for me, as I am using system.js, and migrating to webpack is not an option for me.
Simple workaround: override - ComponentsHelper.getRootViewContainerRef
import { ComponentsHelper } from "ng2-bootstrap/ng2-bootstrap";
ComponentsHelper.prototype.getRootViewContainerRef = function (): ViewContainerRef {
...
}
The problem of access to the to undefined _hostElement and we need to get the correct ViewContainerRef. Replace:
this.root = rootComponent._hostElement.vcRef;
on (if viewContainerRef exists in app component)
this.root = rootComponent._component.viewContainerRef;
This solution works fine for me
Thanks @kraikill
For me only your solution works. Its also the easiest patch for now.
Just to clarify for others, copy/paste the following in your main component (appComponent)
import { ComponentsHelper } from 'ng2-bootstrap/ng2-bootstrap'
ComponentsHelper.prototype.getRootViewContainerRef = function () {
// https://github.com/angular/angular/issues/9293
if (this.root) {
return this.root;
}
var comps = this.applicationRef.components;
if (!comps.length) {
throw new Error("ApplicationRef instance not found");
}
try {
/* one more ugly hack, read issue above for details */
var rootComponent = this.applicationRef._rootComponents[0];
//this.root = rootComponent._hostElement.vcRef;
this.root = rootComponent._component.viewContainerRef;
return this.root;
}
catch (e) {
throw new Error("ApplicationRef instance not found");
}
};
it should fix the issue for NG2 v2.2.1 until an official patch is released by NG2-bootstrap team :)
If you use the solution added to the topic, you have to add set the root view component ref explicitly in the Component where you are calling the modal.
In my case it was not working if I set the root view in AppComponent.
I will add both hacks to topic starter, second one actually described at modals demo page.
Thanks @hassanasad it works for me!
I would like migrate to new angular2 version but this issue with modal windows is stopping me. Do you have any plans to fix this ?
I tried to use method described at top. Before applying my application just would not open modal. After using the fix above my entire application fails with error:
popup.bundle.js:3023 EXCEPTION: config._d.getTime is not a function
For the time being I have reverted to angular 2.0.2 to get around this
I rewrote component injector, testing...
will be able to publish late today or early tomorrow
@valorkin It will be very appreciated
Looking forward to this!
So after talking to @valorkin he let me know that the answer (for now) is at the very top of this thread. I just failed at reading the entire thing lol.
For anyone not wanting to read through the whole post you need to do two things.
Add the following to your constructor.
constructor(private componentsHelper: ComponentsHelper, private vcr: ViewContainerRef) {
componentsHelper.setRootViewContainerRef(vcr);
}
And add the following to your imports
import { ViewContainerRef } from '@angular/core';
import { ComponentsHelper } from 'ng2-bootstrap';
https://github.com/valor-software/ng2-bootstrap/issues/986#issue-177218652
import { ComponentsHelper } from 'ng2-bootstrap';
works starting from v1.1.16-3
and if your had import ... from 'ng2-bootstrap/componets/alert'
now it is just ng2-bootstrap/alert
ok, guys new injection service is working ;)
so I will be updating components to use new service
most probably I will do release with next tag,
on Monday when QA will approve this version it will marked as latest
ya same issue, can't get modal to work...
https://github.com/valor-software/ng2-bootstrap/pull/1318/files#diff-47917cb7752d9ff4c3eddfa99fba920c
working on it, in a while you can check how popovers look like inside ;)
While the given workaround did not fix the issue, here is the version that works for me.
import { Component, ViewContainerRef } from '@angular/core';
import { ComponentsHelper } from 'ng2-bootstrap/ng2-bootstrap';
ComponentsHelper.prototype.getRootViewContainerRef = function () {
// https://github.com/angular/angular/issues/9293
if (this.root) {
return this.root;
}
var comps = this.applicationRef.components;
if (!comps.length) {
throw new Error("ApplicationRef instance not found");
}
try {
/* one more ugly hack, read issue above for details */
var rootComponent = this.applicationRef._rootComponents[0];
//this.root = rootComponent._hostElement.vcRef;
this.root = rootComponent._component.viewContainerRef;
return this.root;
}
catch (e) {
throw new Error("ApplicationRef instance not found");
}
};
@Component({
selector: '......',
template: "......"
})
export class AppComponent {
// As instructed at http://valor-software.com/ng2-bootstrap/#/modals
private viewContainerRef: ViewContainerRef;
public constructor(viewContainerRef: ViewContainerRef) {
// You need this small hack in order to catch application root view container ref
this.viewContainerRef = viewContainerRef;
}
}
@valorkin will you add some comments on https://github.com/valor-software/ng2-bootstrap/issues/986#issuecomment-261277156 please? This injection is really weird, especially if one wants to ship the modals within another module; I need to force people to make this injection in their project just because... Because what?
There are v1.1.16-7
Component helper removed completely, works with 2.3 too
New docs preview available here
http://valorkin.github.io/ng2-bootstrap/
Pay attention to forRoot
Works with v1.1.16-7 :-)
@valorkin I tried installing v1.1.16-7 and am getting 404's for component-loader.js and positioning.js. I am using systemjs. Does this work with systemjs or do I need to switch to webpack/CLI?
NVM I got it working. Had to add .forRoot() to every imported ng2-bootstrap module. And then had to change systemjs like so:
from
'ng2-bootstrap':'npm:ng2-bootstrap',
to
'ng2-bootstrap/ng2-bootstrap':'npm:ng2-bootstrap/bundles/ng2-bootstrap.umd.js',
@crh225 you know that such words can harm? please don't write such things
I am investing huge amount of time in this project
ng4 will be released in march
until that time this project will be renamed
to ngx or ng
@valorkin Thanks for your time on this project it is very helpful to have this module! Keep up the good work!
@conor-mac-aoidh thank you! ;)
reworking docs at the moment, this is how I want to see them at the end
only alert samples are deployed at the moment
http://valorkin.github.io/ng2-bootstrap/#/alerts
@valorkin @conor-mac-aoidh usually +1 is not the best thing to do but I cannot avoid it. Thank you for your contribution to the development of angular2 and its community 馃憤 ! I believe this project helps lots of people and makes angular2 closer to the not experienced users. Don't listen to the ugly people, listen to the good ones :)
same here, amazing job and THANKS for the effort, sure is appreciated!!
Sean
Thanks you so much ;)
@valorkin This issue still persists during runtime of AoT build when I add bsModal div and use shared module to include 'ng2-bootstrap' modules.
EXCEPTION: Uncaught (in promise): Error: Token must be defined!
Error: Token must be defined!
I use Angular 2.4.1, ng2-bootstrap 1.1.16-11
Here is a repo with steps to reproduce:
https://github.com/irsick/ng2-bootstrap-bsModals-issue
Not sure if it's systemjs-specific issue. Apologize in advance if so =)
I use the workaround as described at the top and it worked wel using angular 2.4.3 and ng2-bootstrap v1.1.16. After upgrade to ng2-bootstrap V1.2.1 it breaks and complains that the componentshelper is not exported anymore. The ng2-bootstrap document states that this component is removed.
@TyGp we had this very same issue yesterday. i cloned our repo on another machine and ran npm install we had our package.json set to take major versions of ng2-bootstrap (ala "ng2-bootstrap": "^1.1.16"). Seems like the workaround mentioned here is no longer needed. We removed workaround code mentioned here.
However, we ran quickly into two other breaking changes.
systemjs.config.js needed some tweaking. You can see that from the ng2-bootstrap Sample Repository https://github.com/valor-software/angular2-quickstartNg2BootstrapModule and added reference to each feature module. _you'll want to make sure you note the .forRoot() on the imports array_Most of this stuff is mentioned on the project page. It was our mistake to leave ourselves open to breaking changes via the ^ notation in our package.json. We updated this to ~ to make our updates a bit more intentional. Hope this helps.
This is broken in angular 4 again, and now ComponentsHelper has been removed. I'm unable to show modals from typescript.
EDIT: nm, figured it out, I need to add <script>window.__theme = 'bs4';</script> to the index.html. This should be more prominent on the bootstrap 4 page though.
Most helpful comment
Thanks @kraikill
For me only your solution works. Its also the easiest patch for now.
Just to clarify for others, copy/paste the following in your main component (appComponent)
it should fix the issue for NG2 v2.2.1 until an official patch is released by NG2-bootstrap team :)