Nebular: Context menu does not render after router navigation

Created on 8 Jan 2019  路  26Comments  路  Source: akveo/nebular

Issue type

I'm submitting a ... (check one with "x")

  • [x] bug report
  • [ ] feature request

Issue description

Current behavior:
Following an OAuth2 flow similar to the samples, the user context menu in the header component does not drop-down upon click and yields the following stack trace.

main.a72571efe1e9cccd811a.js:69949 ERROR TypeError: Cannot read property 'appendChild' of null
at NbOverlayContainerAdapter.push../node_modules/@nebular/theme/components/cdk/adapter/overlay-container-adapter.js.NbOverlayContainerAdapter._createContainer (main.a72571efe1e9cccd811a.js:105528)
at NbOverlayContainerAdapter.push../node_modules/@angular/cdk/esm5/overlay.es5.js.OverlayContainer.getContainerElement (main.a72571efe1e9cccd811a.js:11222)
at NbOverlay.push../node_modules/@nebular/theme/components/cdk/overlay/mapping.js.NbOverlay.createHostElement (main.a72571efe1e9cccd811a.js:106080)
at NbOverlay.push../node_modules/@nebular/theme/components/cdk/overlay/mapping.js.NbOverlay.create (main.a72571efe1e9cccd811a.js:106055)
at NbOverlayService.push../node_modules/@nebular/theme/components/cdk/overlay/overlay.js.NbOverlayService.create (main.a72571efe1e9cccd811a.js:106832)
at NbContextMenuDirective.push../node_modules/@nebular/theme/components/context-menu/context-menu.directive.js.NbContextMenuDirective.createOverlay (main.a72571efe1e9cccd811a.js:108818)
at NbContextMenuDirective.push../node_modules/@nebular/theme/components/context-menu/context-menu.directive.js.NbContextMenuDirective.show (main.a72571efe1e9cccd811a.js:108798)
at SafeSubscriber._next (main.a72571efe1e9cccd811a.js:108855)
at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (main.a72571efe1e9cccd811a.js:137557)
at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next (main.a72571efe1e9cccd811a.js:137495)

Expected behavior:
The user context menu will show upon click after router navigation.

Steps to reproduce:
The callback code that's triggering the issue is in the akveo/nebular repo.
https://github.com/akveo/nebular/blob/7e68c20a92dbe8f86ff728f0df6d4e771a0b7408/src/playground/with-layout/oauth2/oauth2-callback.component.ts

I even tried a variation of the existing logic by running it within OnInit and OnDestroy with the appropriate subscription disposable. It yields the same results.
The only thing that makes the user context menu to start rendering again is a hard-refresh of the browser.

Related code:

Other information:

npm, node, OS, Browser

Node, npm: `node --version` (v11.4.0) and `npm --version` (6.4.1)
OS: macOS Mojave
Browser: Chrome

Angular, Nebular

    "@nebular/auth": "3.1.0",
    "@nebular/bootstrap": "3.1.0",
    "@nebular/security": "3.1.0",
    "@nebular/theme": "3.1.0",
bug components needs info quality

Most helpful comment

This issue effectively impedes the usage of the otherwise excellent ContextMenu and Dialog components and it should not be postponed any further

All 26 comments

Yep, having the same issue with _NbPasswordAuthStrategy_.

[EDIT]

The issue only occurs, if the redirect property is set (for either success or failure depending on the case, for me its redirect.success):

// ...
login: {
    endpoint: 'auth',
    method: 'post',
    redirect: {
        success: 'main', // I'm redirecting from route /auth to /main once login was successful
        failure: null
    }
},
// ...

I investigated on that issue in the file .../node_modules/@nebular/auth/components/login/login.component.js.
In the method NbLoginComponent.login() the router object is used to redirect to the configured route, which triggers the described issue.

// ...
NbLoginComponent.prototype.login = function () {
    var _this = this;
    this.errors = [];
    this.messages = [];
    this.submitted = true;
    this.service.authenticate(this.strategy, this.user).subscribe(function (result) {
        _this.submitted = false;
        if (result.isSuccess()) {
            _this.messages = result.getMessages();
        }
        else {
            _this.errors = result.getErrors();
        }
        var redirect = result.getRedirect();
        if (redirect) {
            setTimeout(function () {
                return _this.router.navigateByUrl(redirect); // <-- This line triggers the issue
            }, _this.redirectDelay);
        }
        _this.cd.detectChanges();
    });
};
// ...

Cannot reproduce it. Could you someone consolidate a reproducible example at https://stackblitz.com/github/akveo/nebular-seed?

I can confirm this issue on Nebular 3.4.0

@Mubramaj, could you shed a bit more light, please? What would be the steps? Are there any changes to layout/routes/etc?

Would really appreciate any help on this.

Same error when trying to load nb-select inside Lazy-loaded feature module. A few days ago the same code was working with angular core at v7.2.9 and CDK at v7.3.4

Now i'm getting this same error with angular core at v7.2.13 and CDK at v7.3.7

"@angular/animations": "^7.2.13",
"@angular/cdk": "^7.3.7",
"@angular/common": "^7.2.13",
"@angular/compiler": "^7.2.13",
"@angular/compiler-cli": "^7.2.13",
"@angular/core": "^7.2.13",
"@angular/flex-layout": "^7.0.0-beta.23",
"@angular/forms": "^7.2.13",
"@angular/http": "^7.2.13",
"@angular/platform-browser": "^7.2.13",
"@angular/platform-browser-dynamic": "^7.2.13",
"@angular/router": "^7.2.13",
"@nebular/auth": "3.1.0",
"@nebular/bootstrap": "3.1.0",
"@nebular/security": "3.1.0",
"@nebular/theme": "3.1.0",
"@ng-bootstrap/ng-bootstrap": "^4.1.0"

Hi, this must be propably related also to my issue #1273.
You @nnixaa marked it as fixed and closed it in new nebular version - 3.4.2, but this issue still isn't fixed and the bug is still there!
My Issue #1273 -> the context menu won't open after parent element is "refreshed" (by structural directive). (check this Stackblitz example).

It would be great, if you could check and propably fix this ASAP, because this isn't probably only about NbContextMenu, but I have same problem with Toasters (after parent element is refreshed, the Toasters will stop showing). I'm aware of that this bug affects more Nebular features, than just this 2, which I mentioned.

Same issue for me with nebular 3.5.0 : just after login I have the same error message when I try to open a dialog. No error if I was already logged when I run the application.

same problem

"dependencies": { "@angular/animations": "~8.0.0", "@angular/cdk": "^8.0.0", "@angular/common": "~8.0.0", "@angular/compiler": "~8.0.0", "@angular/core": "~8.0.0", "@angular/forms": "~8.0.0", "@angular/platform-browser": "~8.0.0", "@angular/platform-browser-dynamic": "~8.0.0", "@angular/router": "~8.0.0", "@nebular/auth": "^4.0.0", "@nebular/eva-icons": "4.0.0", "@nebular/theme": "^4.0.0", "@swimlane/ngx-charts": "^11.1.0", "@nebular/bootstrap": "^4.0.0", "angular-in-memory-web-api": "^0.8.0", "eva-icons": "^1.1.1", "ngx-charts": "^3.0.2", "ngx-echarts": "^4.1.1", "angular2-chartjs": "^0.5.1", "bootstrap": "^4.3.1", "chart.js": "^2.8.0", "core-js": "^2.5.4", "rxjs": "~6.4.0", "tslib": "^1.9.0", "zone.js": "~0.9.1" }, "devDependencies": { "@angular-devkit/build-angular": "~0.800.0", "@angular/cli": "~8.0.2", "@angular/compiler-cli": "~8.0.0", "@angular/language-service": "~8.0.0", "@schematics/angular": "~8.0.0", "@types/jasmine": "~3.3.8", "@types/jasminewd2": "~2.0.3", "@types/node": "~8.9.4", "codelyzer": "^5.0.0", "jasmine-core": "~3.4.0", "jasmine-spec-reporter": "~4.2.1", "karma": "~4.1.0", "karma-chrome-launcher": "~2.2.0", "karma-coverage-istanbul-reporter": "~2.0.1", "karma-jasmine": "~2.0.1", "karma-jasmine-html-reporter": "^1.4.0", "protractor": "~5.4.0", "ts-node": "~7.0.0", "tslint": "~5.15.0", "typescript": "~3.4.3" } }

same problem!

I beleave that is something related to NbOverlayContainerAdapter._containerElement member (is showing null in vscode debugger). So, when it calls getContainerElement().appendChild throws the error!

Someone got some palliative solution?

This issue effectively impedes the usage of the otherwise excellent ContextMenu and Dialog components and it should not be postponed any further

I have same issue when combined nbContextMenu directive with nb-route-tabset.
In https://angular-7-master-6mmzen.stackblitz.io/ (Edit URL: https://stackblitz.com/edit/angular-7-master-6mmzen)

[Reproduce steps]

  1. App starts with AboutPage (Click Settings at the top-left corner will show context menu)
  2. Switch to ContactPage
    At this time, nbContextMenu in shared component will not work anymore.

I have the same problem.
Error is as follows :-
ERROR TypeError: Cannot read property 'appendChild' of null at NbOverlayContainerAdapter._createContainer (index.js:997) at NbOverlayContainerAdapter.getContainerElement (overlay.js:766) at NbOverlay._createHostElement (overlay.js:3177) at NbOverlay.create (overlay.js:3136) at NbOverlayService.create (index.js:1464) at NbSelectComponent.createOverlay (index.js:18650) at NbSelectComponent.attachToOverlay (index.js:18632) at NbSelectComponent.show (index.js:18537) at SafeSubscriber._next (index.js:18673) at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)

I also have the same problem with nebular toastr. Its not working in my lazy loaded feature module.

I still got the issue in version 4.5.0

ERROR TypeError: Cannot read property 'appendChild' of null
    at NbOverlayContainerAdapter._createContainer (index.js:1043)
    at NbOverlayContainerAdapter.getContainerElement (overlay.js:768)
    at NbOverlay._createHostElement (overlay.js:3203)
    at NbOverlay.create (overlay.js:3162)
    at NbOverlayService.create (index.js:1647)
    at NbDynamicOverlay.createOverlay (index.js:11878)
    at NbDynamicOverlay.show (index.js:11841)
    at SafeSubscriber._next (index.js:12077)
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
    at SafeSubscriber.next (Subscriber.js:122)

3.6.2 seems to fix this issue

3.6.2 seems to fix this issue

no it does not, at least when there are lazy-loaded modules in the way

I still got the issue in version 4.5.0

ERROR TypeError: Cannot read property 'appendChild' of null
    at NbOverlayContainerAdapter._createContainer (index.js:1043)
    at NbOverlayContainerAdapter.getContainerElement (overlay.js:768)
    at NbOverlay._createHostElement (overlay.js:3203)
    at NbOverlay.create (overlay.js:3162)
    at NbOverlayService.create (index.js:1647)
    at NbDynamicOverlay.createOverlay (index.js:11878)
    at NbDynamicOverlay.show (index.js:11841)
    at SafeSubscriber._next (index.js:12077)
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
    at SafeSubscriber.next (Subscriber.js:122)

same here.. so frustrating, can't get around it with Context Menus, had to swap a different navigation menu system for production release

@lepidotteri I used Nebular Auth and had to write a custom AuthComponent that doesn't use <nb-layout> itself, by default it does:

https://github.com/akveo/nebular/blob/1e1a293d189cc63f15a53c9e69682ee754fbc149/src/framework/auth/components/auth.component.ts#L16-L33

From my understanding the menu only works correctly if the <nb-layout> stays consistent throughout navigation.

@lepidotteri I used Nebular Auth and had to write a custom AuthComponent that doesn't use <nb-layout> itself, by default it does:

https://github.com/akveo/nebular/blob/1e1a293d189cc63f15a53c9e69682ee754fbc149/src/framework/auth/components/auth.component.ts#L16-L33

From my understanding the menu only works correctly if the <nb-layout> stays consistent throughout navigation.

Thank you @niklasravnsborg, I had suspected as much; I didn't go that far but I did change the auth-module routes to test the behavior and it was working fine then.

I think they should either:

  1. change the component to be more standalone and resilient
  2. make NbMenuComponent more suitable (doesn't even have orientation atm?) and customizable for top-bar navigation purposes

I have the same problem with 4.6.0 version of nebular.

<nb-action *ngIf="isLoggedIn">
    <nb-user [name]="user?.name" [picture]="'https://www.gravatar.com/avatar/' + user?.email_hash"
      [nbContextMenu]="accountMenuActions" nbContextMenuTag="account-menu" nbContextMenuTrigger="hover">
    </nb-user>
</nb-action>

If i logout and login again i have the same error.

ERROR TypeError: Cannot read property 'appendChild' of null
    at NbOverlayContainerAdapter._createContainer (index.js:1043)
    at NbOverlayContainerAdapter.getContainerElement (overlay.js:768)
    at NbOverlay._createHostElement (overlay.js:3203)
    at NbOverlay.create (overlay.js:3162)
    at NbOverlayService.create (index.js:1637)
    at NbDynamicOverlay.createOverlay (index.js:11473)
    at NbDynamicOverlay.show (index.js:11436)
    at SafeSubscriber._next (index.js:11672)
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
    at SafeSubscriber.next (Subscriber.js:122)

It can aslo appear after navigation on specific routes, always the same routes.

What @niklasravnsborg suggested worked for me. The nb-layout tag needs to be consistent in the outer layout. i.e. it should always be the same outer nb-layout tag which is containing other layouts

Whats the fix for this? im having same issue.

I don't remember exactly but do you use multiple <nb-layout> in your projects ?
Personally i used many <nb-layout> in multiple vues, when i found a alternative to this it fixed so i think is linked :)

I have the same problem with 4.6.0 version of nebular.

<nb-action *ngIf="isLoggedIn">
    <nb-user [name]="user?.name" [picture]="'https://www.gravatar.com/avatar/' + user?.email_hash"
      [nbContextMenu]="accountMenuActions" nbContextMenuTag="account-menu" nbContextMenuTrigger="hover">
    </nb-user>
</nb-action>

If i logout and login again i have the same error.

ERROR TypeError: Cannot read property 'appendChild' of null
    at NbOverlayContainerAdapter._createContainer (index.js:1043)
    at NbOverlayContainerAdapter.getContainerElement (overlay.js:768)
    at NbOverlay._createHostElement (overlay.js:3203)
    at NbOverlay.create (overlay.js:3162)
    at NbOverlayService.create (index.js:1637)
    at NbDynamicOverlay.createOverlay (index.js:11473)
    at NbDynamicOverlay.show (index.js:11436)
    at SafeSubscriber._next (index.js:11672)
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
    at SafeSubscriber.next (Subscriber.js:122)

It can aslo appear after navigation on specific routes, always the same routes.

I'm also experiencing the exact same behavior, hope there are any updates to this bug

I have experienced the same error: ERROR TypeError: Cannot read property 'appendChild' of null while I was playing with the nb-user component:

<nb-action class="user-action" *ngIf="isAuth">
      <nb-user
        [nbContextMenu]="userMenu"
        nbContextMenuTag="user-context-menu"
        [name]="user?.email"
        [onlyPicture]="userPictureOnly"
        [picture]="user?.picture">
      </nb-user>
</nb-action>

I could not load the userMenu context menu, only the hard refresh was bringing the things to normal...but this was not the ideal solution.

My main app component used the <app-header> component which had the offending <nb-user> component, as shown below :

<nb-layout>
  <nb-layout-header fixed>
    <app-header></app-header>
  </nb-layout-header>

  <nb-layout-column>
    <router-outlet></router-outlet>
  </nb-layout-column>

  <nb-layout-footer fixed>
    Footer
  </nb-layout-footer>
</nb-layout>

During route changes, my <router-outlet></router-outlet> was being replaced by the auth component which is presented below:

<nb-layout>
  <nb-layout-column>
    <nb-card>
      <nb-card-header>
        <nav class="navigation">Authentication</nav>
      </nb-card-header>
      <nb-card-body>
        <app-auth-block>
          <router-outlet></router-outlet>
        </app-auth-block>
      </nb-card-body>
    </nb-card>
  </nb-layout-column>
</nb-layout>

The surprising fix was to remove the <nb-layout> and <nb-layout-column> parts from my auth component...thus here it is how it looks now:

<nb-card>
  <nb-card-header>
    <nav class="navigation">Authentication</nav>
  </nb-card-header>
  <nb-card-body>
    <app-auth-block>
      <router-outlet></router-outlet>
    </app-auth-block>
  </nb-card-body>
</nb-card>

Thanks to this trick the error is gone and I can see the context menu while clicking on the user icon.

I hope this confirms that the error still exists, even in @nebular/theme: "^5.1.0" version. Plus, the suggestions from previous people here, that having only one <nb-layout> surprisingly fixes this weird error. Thank you guys!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

NikhilGangurde picture NikhilGangurde  路  3Comments

ChristianVega5421 picture ChristianVega5421  路  3Comments

suku-h picture suku-h  路  3Comments

obarazan picture obarazan  路  3Comments

muysewinkel picture muysewinkel  路  4Comments