Components: mat-sidenav and mad-sidenav-container issues with 'TypeError: Cannot read property 'create' of undefined

Created on 2 Feb 2018  路  7Comments  路  Source: angular/components

Bug, feature request, or proposal:

I have created a working app where there are no problems using your StackBlitz templates. However when refactoring my code to use the material components, I am coming up against the problem of console error surrounding the element with console showing:

TypeError: Cannot read property 'create' of undefined at MatSidenav.ngAfterContentInit (sidenav.js:326) at callProviderLifecycles

What is the expected behavior?

Expected behaviour is for this error not to occur such that I can use the component as expect and recreate what I made on StackBlitz

What is the current behavior?

See above for description

StackBlitz and steps to reproduce the issue:

StackBlitz Demo which shows your issue:
Detailed Reproduction Steps:

Basically the problem will be found within app.component.html... Everything is imported correctly and material components can be used as normal. However, the following tags make things fail...

Commenting these and their corresponding closing tags out, you are left with a that works fine... For some reason it seems to be the sidenav that is causing issues?

What is the use-case or motivation for changing an existing behavior?

Without the sidenav component, my code will need a lot more finessing and changing, and will not work in the way intended with simple material design components.

Which versions of AngularJS, Material, OS, and browsers are affected?

Angular 5
Material 5.1.1
Windows 10
Chrome

Is there anything else we should know? Stack Traces, Screenshots, etc.

needs clarification

Most helpful comment

This is an es6 problem - reverting to es5 resolves it

All 7 comments

Your stackblitz reproduction has some issues: the bindings are incomplete and RouterModule isn't loaded. Can you update it to show the issue you're reporting here?

I agree with @jelbourn , I can't reproduce with that error stackblitz (after fixing the issues)

I am getting that error locally, will add more detail as I get it; but the most obvious hint (I am investigating now) is the preceding message; could not find HammerJS

10:58:35.610 core.js:136 Could not find HammerJS. Certain Angular Material components may not work correctly.
10:58:36.373 AppComponent.html:19 ERROR TypeError: Cannot read property 'create' of undefined
    at MatSidenav.ngAfterContentInit (sidenav.js:328)

All of this happened in the middle of changing tsconfig.json because of (probably unrelated) issues like 'Cannot find name WeakMap' ; I changed to target: 'es6' ... but I'll look at installing / importing hammerjs first.

UPDATE
the hammerjs issue is fixed as described in StackOverflow (and documented on material.io Getting Started : Gesture Support); but the original error "Cannot read property of 'create'" in MatSidenav -- is still there.

So I'll investigate another coincidence, a different error which happens later : MatSidenav fails again:

11:09:56.966 AppComponent.html:19 ERROR TypeError:  Cannot read property 'isBrowser' of undefined
    at MatSidenav.ngAfterContentChecked (sidenav.js:339)

The implementation:

ngAfterContentChecked() {
        // Enable the animations after the lifecycle hooks have run, in order to avoid animating
        // drawers that are open by default. When we're on the server, we shouldn't enable the
        // animations, because we don't want the drawer to animate the first time the user sees
        // the page.
        if (this._platform.isBrowser) {
            this._enableAnimations = true;
        }
    }

UPDATE 2 (with hacky fix)
MatSidenav extends MatDrawer
The parent class MatDrawer has explicit ctorParameters
(in .\node_modules\@angular\material\esm2015\sidenav.js line 469)

MatDrawer.ctorParameters = () => [
    { type: ElementRef, },
    { type: FocusTrapFactory, },
    ...

But the child class, MatSidenav, doesnt have an explicit constructor, so its ctorParameters are empty:
(in .\node_modules\@angular\material\esm2015\sidenav.js line 917)

MatSidenav.ctorParameters = () => [];

So when a MatSidenav is instantiated, its constructor calls super constructor; MatDrawer, with an empty arguments array. This means MatDrawer won't have the factories/services it needs -- which is the heart of this error.

    constructor() {
        super(...arguments);
        this._fixedInViewport = false;
        this._fixedTopGap = 0;
        this._fixedBottomGap = 0;
    }

If I edit my node_modules file (.\node_modules\@angular\material\esm2015\sidenav.js) to make MatSidenav.ctorParameters consistent with its parent

MatSidenav.ctorParameters = MatDrawer.ctorParameters;

This prevents the issue; the correct services/factories are injected into the child, therefore passed to the parent, and no errors.

This lack of explicit constructor in MatSidenav -extends-> MatDrawer is not the case with MatAnchor-extends->MatButton; the MatAnchor class explicitly redefines a constructor and which depends on 3 parameters to be injected even though the constructor is exactly the same (same 3 parameters) as its parent class; MatButton.

UPDATE 3 (with better fix)
I mentioned I was doing all this when I switched to target: 'es6' (to avoid 'Cannot find name WeakMap')
If I change back to target: 'es5' (and include the necessary lib in my tsconfig.json; which avoids 'Cannot find name WeakMap') then I don't see the MatSidenav issue...

...
    "lib": [
      "es2017",
      "dom"
    ],
...

I notice changing the target = 'es5', now the codefile executed is this one:

  • ./node_modules/@angular/material/esm5/sidenav.es5.js

(instead of target = 'es6' which used this one:)

  • .\node_modules\@angular\material\esm2015\sidenav.js

I guess that is exactly what I should expect by changing my target. Moreover, when the MatSidenav constructor in the first file ( es5, esm5/sidenav.es5.js ) executes, the constructor is passed the appropriate parameters even though MatSidenav.ctorParameters = function () { return []; };.

When the constructor in the second file (es6, esm2015\sidenav.js ) executes, the constructor is not passed the appropriate parameters as I explained before (maybe I'm missing some polyfill? Maybe polyfills are unrelated....)

And I only experienced the issue locally. stackblitz looks great, but I don't see its tsconfig.json files in its example projects (i.e. nor in @physicsboy nor my stackblitz demo's here), so stackblitz "just works" . How does stackblitz configure TypeScript settings for its angular projects? I need to learn more about typescript configs and targets,...

This is an es6 problem - reverting to es5 resolves it

I had to change to ES6 and cannot revert to ES5 because of some build issues. So I changed my ng start script to use aot locally, too, and now it works.

Add the following import in your polyfills.ts
import 'hammerjs/hammer';

(don't forget to install hammerjs via npm)

This is an es6 problem - reverting to es5 resolves it

Switching back to es5 worked for me, nit sure what aspect of es6 sets it off,

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MurhafSousli picture MurhafSousli  路  3Comments

theunreal picture theunreal  路  3Comments

alanpurple picture alanpurple  路  3Comments

jelbourn picture jelbourn  路  3Comments

Hiblton picture Hiblton  路  3Comments