Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'ngDoCheck' of null #393

Closed
crabouif opened this issue Aug 27, 2017 · 11 comments · Fixed by #394
Closed
Labels
bug has pr A PR has been created to address this issue P1 Urgent issue that should be resolved before the next re-lease

Comments

@crabouif
Copy link

crabouif commented Aug 27, 2017

I have a form with some flex layout inside. But sometimes when I change the route by a link, the app crash with error

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'ngDoCheck' of null

I found that happen in file flex-layout.es5.js line 2906. The piece of code is

ClassDirective.prototype.ngDoCheck = function () {
        if (!this._classAdapter.hasMediaQueryListener) {
            this._configureMQListener();
        }
        this._ngClassInstance.ngDoCheck();
};

Then if I patch to

    ClassDirective.prototype.ngDoCheck = function () {
        if (!this._classAdapter.hasMediaQueryListener) {
            this._configureMQListener();
        }
        if (this._ngClassInstance) {
            this._ngClassInstance.ngDoCheck();
        }
    };

the issue doesn't apear anymore.

My context is:

@angular/cli: 1.3.2
node: 7.10.1
os: linux x64
@angular/animations: 4.3.6
@angular/cdk: 2.0.0-beta.8
@angular/common: 4.3.6
@angular/compiler: 4.3.6
@angular/core: 4.3.6
@angular/flex-layout: 2.0.0-beta.9
@angular/forms: 4.3.6
@angular/http: 4.3.6
@angular/material: 2.0.0-beta.8
@angular/platform-browser: 4.3.6
@angular/platform-browser-dynamic: 4.3.6
@angular/router: 4.3.6
@angular/cli: 1.3.2
@angular/compiler-cli: 4.3.6
@angular/language-service: 4.3.6

I dont know if its related, but I have a reactive form and each time the user change something, I save the values. This issue happen after a various number of modifications (and so saves).

    form.valueChanges
      .debounceTime(1000)
      .distinctUntilChanged()
      .filter(v => form.valid)
      .subscribe(v => {
        this.state = FormModelState.Saving;
        (<Observable<Response>>this.save())
          .subscribe(res => {
              this.state = FormModelState.Saved;
              this.error = "";
            },
            e => {
              this.state = FormModelState.SaveError;
              this.error = e;
            }
          );
      });

Thanks.

@thaihuyhung
Copy link

thaihuyhung commented Aug 27, 2017

I faced the same issue in many places of my Application.

@ThomasBurleson
Copy link
Contributor

ThomasBurleson commented Aug 27, 2017

@crabouif - This error you are experiencing is very weird since the constructor always ensures an valid instance of the this._ngClassInstance (https://github.com/angular/flex-layout-builds/blob/v2.0.0-beta.9/%40angular/flex-layout.es5.js#L2738-L2740)

function ClassDirective(monitor, _ngEl, _renderer, _oldRenderer, _iterableDiffers, _keyValueDiffers, _ngClassInstance) {
    var _this = _super.call(this, monitor, _ngEl, _renderer) || this;
    _this.monitor = monitor;
    _this._ngClassInstance = _ngClassInstance;
    _this._classAdapter = new BaseFxDirectiveAdapter('class', monitor, _ngEl, _renderer);
    _this._ngClassAdapter = new BaseFxDirectiveAdapter('ngClass', monitor, _ngEl, _renderer);
    if (!_this._ngClassInstance) {
        _this._ngClassInstance = new NgClass(_iterableDiffers, _keyValueDiffers, _ngEl, _oldRenderer);
    }
    return _this;
}

So I am completely confused how your reference could be null. Can you provide an online Plunkr that reproduces this error ?

@crabouif
Copy link
Author

crabouif commented Aug 28, 2017

First thanks for your reactivity!

Sorry, for the moment, I can't do the Plunkr. But what I can say is this occures when the view is destroying. Maybe this this._ngClassInstance is destroyed before the calling of ngDoCheck ?

Here is the call stack.

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'ngDoCheck' of null
TypeError: Cannot read property 'ngDoCheck' of null
    at ClassDirective.webpackJsonp.../../../flex-layout/@angular/flex-layout.es5.js.ClassDirective.ngDoCheck (vendor.bundle.js:105741)
    at checkAndUpdateDirectiveInline (vendor.bundle.js:98799)
    at checkAndUpdateNodeInline (vendor.bundle.js:100297)
    at checkAndUpdateNode (vendor.bundle.js:100236)
    at debugCheckAndUpdateNode (vendor.bundle.js:101097)
    at debugCheckDirectivesFn (vendor.bundle.js:101038)
    at Object.eval [as updateDirectives] (ng:///AppModule/PatientEditComponent.ngfactory.js:1462)
    at Object.debugUpdateDirectives [as updateDirectives] (vendor.bundle.js:101023)
    at checkAndUpdateView (vendor.bundle.js:100203)
    at callWithDebugContext (vendor.bundle.js:101423)
    at ClassDirective.webpackJsonp.../../../flex-layout/@angular/flex-layout.es5.js.ClassDirective.ngDoCheck (vendor.bundle.js:105741)
    at checkAndUpdateDirectiveInline (vendor.bundle.js:98799)
    at checkAndUpdateNodeInline (vendor.bundle.js:100297)
    at checkAndUpdateNode (vendor.bundle.js:100236)
    at debugCheckAndUpdateNode (vendor.bundle.js:101097)
    at debugCheckDirectivesFn (vendor.bundle.js:101038)
    at Object.eval [as updateDirectives] (ng:///AppModule/PatientEditComponent.ngfactory.js:1462)
    at Object.debugUpdateDirectives [as updateDirectives] (vendor.bundle.js:101023)
    at checkAndUpdateView (vendor.bundle.js:100203)
    at callWithDebugContext (vendor.bundle.js:101423)
    at resolvePromise (polyfills.bundle.js:3340)
    at resolvePromise (polyfills.bundle.js:3311)
    at polyfills.bundle.js:3389
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (polyfills.bundle.js:2970)
    at Object.onInvokeTask (vendor.bundle.js:91829)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (polyfills.bundle.js:2969)
    at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask (polyfills.bundle.js:2737)
    at drainMicroTaskQueue (polyfills.bundle.js:3147)
    at ZoneTask.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (polyfills.bundle.js:3048)
    at invokeTask (polyfills.bundle.js:3972)

And some callstack print screen.

Here is the destroyed view. I'm not sure because that is no flex inside?!

image

Then here the calling of destroy.

image

image

Thanks!

@ThomasBurleson
Copy link
Contributor

ThomasBurleson commented Aug 28, 2017

@crabouif - It appears that your template is only using class without any responsive features (eg class.xs="", etc). For our team testing purposes, can you paste your HTML template below?

Note: the Flex-Layout StyleDirective and ClassDirective instances should deactivate if responsive keys are not used. E.g. the [class] selector should be removed.

This is a bug.

@crabouif
Copy link
Author

crabouif commented Aug 28, 2017

Here is my HTML:

<md-toolbar class="sidenav-toolbar">
  <span *ngIf="isNew">Nouveau patient</span>
  <span *ngIf="!isNew">Modification du patient</span>

  <span class="fill-remaining-space"></span>

  <df-form-model-state></df-form-model-state>
</md-toolbar>

<form #patientForm [formGroup]="patient" novalidate>
  <div fxLayout="row" fxLayoutAlign="start none" class="fields-row">
    <div fxLayout="column" fxLayoutAlign="start none" class="fields-column left-part">

      <md-card class="address-info">
        <md-card-header>Personne</md-card-header>
        <div class="fields-row" formGroupName="person">
          <md-input-container>
            <input formControlName="politness" mdInput placeholder="Politesse" [mdAutocomplete]="autoPolitness">
          </md-input-container>
          <md-autocomplete #autoPolitness="mdAutocomplete">
            <md-option value="Madame">Madame</md-option>
            <md-option value="Monsieur">Monsieur</md-option>
          </md-autocomplete>
        </div>
        <div fxLayout="row" fxLayoutAlign="start none" class="fields-row" formGroupName="person">
          <md-input-container>
            <input formControlName="firstName" mdInput placeholder="Prénom">
            <md-hint *ngIf="patient.hasError('required', 'person.firstName')" [ngStyle]="{'color': 'red'}" align="start">Le prénom est requis.</md-hint>
          </md-input-container>
          <md-input-container>
            <input formControlName="lastName" mdInput placeholder="Nom" />
            <md-hint *ngIf="patient.hasError('required', 'person.lastName')" [ngStyle]="{'color': 'red'}" align="start">Le nom est requis.</md-hint>
          </md-input-container>
        </div>
        <div class="fields-row" formGroupName="person">
          <md-input-container>
            <input formControlName="address" mdInput placeholder="Adresse (rue et numéro)">
          </md-input-container>
        </div>
        <div fxLayout="row" fxLayoutAlign="start none" class="fields-row" formGroupName="person">
          <md-input-container formGroupName="city" style="width:30%;">
            <input formControlName="zipCode" mdInput placeholder="NPA">
          </md-input-container>
          <md-input-container formGroupName="city">
            <input formControlName="name" mdInput placeholder="Localité">
            <md-hint *ngIf="patient.hasError('required', 'person.city.zipCode') || patient.hasError('required', 'person.city.name')"
              [ngStyle]="{'color': 'red'}" align="start">La personne doit au moins avoir une localité comme adresse.</md-hint>
          </md-input-container>
        </div>
      </md-card>

      <md-card class="patient-info">
        <md-card-header>Patient</md-card-header>
        <md-input-container>
          <input type="number" formControlName="patientNumber" mdInput placeholder="Numéro du patient">
        </md-input-container>
      </md-card>
    </div>

    <div fxLayout="column" fxLayoutAlign="start none" class="fields-column right-part" formGroupName="person">
      <md-card class="comm-info">
        <md-card-header>Communication</md-card-header>
        <md-input-container>
          <input formControlName="phone" mdInput placeholder="Téléphone">
        </md-input-container>
        <md-input-container>
          <input formControlName="email" mdInput placeholder="E-Mail">
          <md-hint *ngIf="patient.get('person.email').value && patient.hasError('pattern', 'person.email')" [ngStyle]="{'color': 'red'}" align="start">E-Mail non valide.</md-hint>
        </md-input-container>
      </md-card>

      <md-card class="other-info">
        <md-card-header>Autres</md-card-header>
        <md-input-container>
          <input mdInput dfInputDate formControlName="birthDate" [mdDatepicker]="birthDatePicker" placeholder="Date de naissance">
          <button mdSuffix [mdDatepickerToggle]="birthDatePicker"></button>
        </md-input-container>
        <md-datepicker #birthDatePicker></md-datepicker>
        <md-select formControlName="gender" placeholder="Genre (sexe)">
          <md-option value="male">Masculin</md-option>
          <md-option value="female">Féminin</md-option>
          <md-option value="unknown">Inconnu</md-option>
        </md-select>
        <md-hint *ngIf="patient.hasError('required', 'person.gender')" [ngStyle]="{'color': 'red', 'font-size': '75%'}" align="start">Le genre est requis.</md-hint>
        <md-input-container>
          <input formControlName="avsNumber" mdInput placeholder="N° AVS">
          <md-hint *ngIf="patient.hasError('pattern', 'person.avsNumber')" [ngStyle]="{'color': 'red'}" align="start">N° AVS non valide.</md-hint>
        </md-input-container>
        <md-select formControlName="languageIsoCode" placeholder="Langue">
          <md-option value="fr">Français</md-option>
          <md-option value="de">Allemand</md-option>
          <md-option value="it">Italien</md-option>
          <md-option value="en">Anglais</md-option>
        </md-select>
      </md-card>
    </div>
  </div>
</form>

Thanks.

ThomasBurleson added a commit that referenced this issue Aug 28, 2017
The host `class` attribute should be considered static and should not be used as a ClassDirective selector. This means that with responsive APIs, the ClassDirective will not be instantiated for elements using only the `class` attribute.

* Use the `class` attribute as a responsive fallback value only.
* Improve support of the ngClass directive for string and object assignments.

Fixes #393.
@ThomasBurleson ThomasBurleson added P1 Urgent issue that should be resolved before the next re-lease bug labels Aug 28, 2017
@ThomasBurleson ThomasBurleson added this to the v2.0.0-beta.10 milestone Aug 28, 2017
@ThomasBurleson ThomasBurleson added the has pr A PR has been created to address this issue label Aug 28, 2017
ThomasBurleson added a commit that referenced this issue Aug 28, 2017
The host `class` attribute should be considered static and should not be used as a ClassDirective selector. This means that with responsive APIs, the ClassDirective will not be instantiated for elements using only the `class` attribute.

* Use the `class` attribute as a responsive fallback value only.
* Improve support of the ngClass directive for string and object assignments.

Fixes #393.
ThomasBurleson added a commit that referenced this issue Aug 28, 2017
… be used as a ClassDirective selector. This means that without associated responsive APIs, the ClassDirective will not be instantiated for elements using only the `class` attribute.

* Use the `class` attribute as a responsive fallback value only.
* Improve support of the ngClass directive for string and object assignments.

Fixes #393.
@ThomasBurleson
Copy link
Contributor

@crabouif - Here is a working Plunkr rendering your template (using Beta.9).

screen shot 2017-08-28 at 12 25 42 pm

I do not see any issues.

@Splaktar
Copy link
Member

Splaktar commented Aug 28, 2017

I'm seeing this too now that I've updated to beta.9. This wasn't an issue in beta.8. The exception points to the following element:

<span class="autoCompleteSeparator">-</span>

That element is contained in the following div:

<div fxLayout="row" fxLayoutWrap fxLayoutAlign="start center" [formGroup]="parentForm">

It only occurs if I've interacted with the component and then clicked on an element that navigates me away (where the component will be destroyed).

ThomasBurleson added a commit that referenced this issue Aug 28, 2017
… be used as a ClassDirective selector. This means that without associated responsive APIs, the ClassDirective will not be instantiated for elements using only the `class` attribute.

* Use the `class` attribute as a responsive fallback value only.
* Improve support of the ngClass directive for string and object assignments.

Fixes #393.
@ThomasBurleson
Copy link
Contributor

@Splaktar - this should be fixed in PR #394

ThomasBurleson added a commit that referenced this issue Aug 31, 2017
… be used as a ClassDirective selector. This means that without associated responsive APIs, the ClassDirective will not be instantiated for elements using only the `class` attribute.

* Use the `class` attribute as a responsive fallback value only.
* Improve support of the ngClass directive for string and object assignments.

Fixes #393.
@naveedahmed1
Copy link

I am also facing this issue even with latest release 2.0.0-beta.9

ThomasBurleson added a commit that referenced this issue Sep 5, 2017
The host `class` attribute should be considered static and should not be used as a ClassDirective selector.

This means that without associated responsive APIs,
the ClassDirective will not be instantiated for elements using only the `class` attribute.

* Use the `class` attribute as a responsive fallback value only.
* Improve support of the ngClass directive for string and object assignments.

Fixes #393.
tinayuangao pushed a commit that referenced this issue Sep 7, 2017
…ve. (#394)

The host `class` attribute should be considered static and should not be used as a ClassDirective selector.

This means that without associated responsive APIs,
the ClassDirective will not be instantiated for elements using only the `class` attribute.

* Use the `class` attribute as a responsive fallback value only.
* Improve support of the ngClass directive for string and object assignments.

Fixes #393.
@roelzkie15
Copy link

roelzkie15 commented Oct 18, 2017

I had the same issue when using flex-layout beta.9 but was able to fix this by downgrading to beta.8

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug has pr A PR has been created to address this issue P1 Urgent issue that should be resolved before the next re-lease
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants