ngx-select-ex icon indicating copy to clipboard operation
ngx-select-ex copied to clipboard

ExpressionChangedAfterItHasBeenCheckedError with autoSelectSingleOption

Open cyphercodes96 opened this issue 7 years ago • 17 comments
trafficstars

  <ngx-select
    [allowClear]="true"
    id="dental_chart"
    [items]="data"
    [(ngModel)]="activeChart"
    [ngModelOptions]="{standalone: true}"
    (select)="selected()"
    [autoSelectSingleOption]="true"
    (remove)="removed($event)"
    placeholder="No Chart Selected">
  </ngx-select>

This is my html select When [autoSelectSingleOption] exists I get this error: ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'model: undefined'. Current value: 'model: 7'. at viewDebugError (core.js:8445) at expressionChangedAfterItHasBeenCheckedError (core.js:8433) at checkBindingNoChanges (core.js:8535) at checkNoChangesNodeInline (core.js:11401) at checkNoChangesNode (core.js:11390) at debugCheckNoChangesNode (core.js:11997) at debugCheckDirectivesFn (core.js:11925) at Object.eval [as updateDirectives] (AddPlanComponent.html:20) at Object.debugUpdateDirectives [as updateDirectives] (core.js:11914) at checkNoChangesView (core.js:11289)

View_AddPlanComponent_1 @ AddPlanComponent.html:20
  push../node_modules/@angular/core/fesm5/core.js.DebugContext_.logError @
  push../node_modules/@angular/core/fesm5/core.js.ErrorHandler.handleError @
  (anonymous) @
  push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @
  push../node_modules/zone.js/dist/zone.js.Zone.run @
  push../node_modules/@angular/core/fesm5/core.js.NgZone.runOutsideAngular @
  push../node_modules/@angular/core/fesm5/core.js.ApplicationRef.tick @
  (anonymous) @
  push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @
  onInvoke @
  push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @
  push../node_modules/zone.js/dist/zone.js.Zone.run @
  push../node_modules/@angular/core/fesm5/core.js.NgZone.run @
  next @
  schedulerFn @
  push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub @
  push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next @
  push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next @
  push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @
  push../node_modules/rxjs/_esm5/internal/Subject.js.Subject.next @
  push../node_modules/@angular/core/fesm5/core.js.EventEmitter.emit @
  checkStable @
  onHasTask @
  push../node_modules/zone.js/dist/zone.js.ZoneDelegate.hasTask @
  push../node_modules/zone.js/dist/zone.js.ZoneDelegate._updateTaskCount @
  push../node_modules/zone.js/dist/zone.js.Zone._updateTaskCount @
  push../node_modules/zone.js/dist/zone.js.Zone.runTask @
  drainMicroTaskQueue @
  push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @
  invokeTask @
  globalZoneAwareCallback

When i remove it i don't get any errors

cyphercodes96 avatar Jun 19 '18 11:06 cyphercodes96

@cyphercodes96 Sorry, but I can't reproduce it. Please, make an example to demonstrate the bug there: https://stackblitz.com/

optimistex avatar Jun 19 '18 15:06 optimistex

I just got the same error while using [defaultValue] in combination with formControlName, might be related.

artemzakharov avatar Jun 19 '18 17:06 artemzakharov

@artemzakharov There is a lot of automated tests. And I tested it my own hands. But I can't catch it. An exemple to reproduce will be better than a long toughts.

optimistex avatar Jun 19 '18 17:06 optimistex

I got the exact steps to reproduce this.

karthikv-26 avatar Jun 19 '18 21:06 karthikv-26

@karthikv-26 Cool! Will you tell of them? Or make a live example.

optimistex avatar Jun 19 '18 21:06 optimistex

Here it is.

  1. Have 2 ngx multi option typeaheads.
  2. Focus on the first type ahead.
  3. You'll see results. select one.
  4. Now focus on the second type ahead.
  5. Again You'll see results. select one.
  6. Now try to focus on the first list and second repeatedly.
  7. It throws the expression checked error.

karthikv-26 avatar Jun 19 '18 21:06 karthikv-26

First of all thank you for this component. It works very well in most of the scenarios except a few minor issues.. :)

karthikv-26 avatar Jun 19 '18 21:06 karthikv-26

@karthikv-26 I glad that it is useful for you! Thank you for the description of the bug case. I'll check it little later and attempt to fix it.

optimistex avatar Jun 19 '18 21:06 optimistex

You're welcome my friend.

Here is the error. (NgxSelectComponent.html:68)

unhandled Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'. at viewDebugError (core.es5.js:8420) at expressionChangedAfterItHasBeenCheckedError (core.es5.js:8398) at checkBindingNoChanges (core.es5.js:8562) at checkNoChangesNodeInline (core.es5.js:12423) at checkNoChangesNode (core.es5.js:12397) at debugCheckNoChangesNode (core.es5.js:13174) at debugCheckDirectivesFn (core.es5.js:13076) at Object.eval [as updateDirectives] (NgxSelectComponent.html:68) at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:13058) at checkNoChangesView (core.es5.js:12217)

karthikv-26 avatar Jun 19 '18 21:06 karthikv-26

I tried to reproduce, but still nothing: https://stackblitz.com/edit/ngx-select-ex-issues-90?file=app/app.component.ts

optimistex avatar Jun 19 '18 21:06 optimistex

I was able to solve this by adding change detection code in blur event handler of the component.

this.ch.detectChanges();

Hope it helps someone.

karthikv-26 avatar Jun 19 '18 23:06 karthikv-26

Yes, it helps.

The blur fired by closing the menu. It usually happens by clicking mouse outside. And it has some delay because of it fired by DOM events. If you changing something from blur then you can get the errors.

Currently, I do not figure out something better than wrapping a code in the blur into setTimeout(() => {...}, 0). Now, it works for my general project.

I do not like this solution and maybe later I'll figure out how to do it better.

optimistex avatar Jun 19 '18 23:06 optimistex

@optimistex Good Morning.

The way you're trying to replicate the issue is wrong, in your reproduction link, you have declared an ngx-select dropdown, passed an object as predefined in the component with over 5 value's inside. We need the ngx-select template to only have one data / option in it, with [autoSelectSingleOption]="true" enabled, so that it selects that data / option by default automatically ( only if there is single data/option available )

Bind the selected value to a class object with [(ngModel)] so that we're on the same page.

P.S: don't assign value's instantly to the data object. After component initialization, on ngOnInIt() function, assign a value (ONLY ONE OPTION) to selectItems1

info: i was capable of reproducing it on your own stackblitz script following the steps mentioned above

cyphercodes96 avatar Jun 20 '18 07:06 cyphercodes96

@optimistex Anything?

cyphercodes96 avatar Jul 23 '18 08:07 cyphercodes96

@cyphercodes96 Make an example for show the bug: https://stackblitz.com/edit/ngx-select-ex-issues-90?file=app/app.component.ts

I want to help, but I have no so much time to investigate everything... Help me to see the issue and I try to find time to fix it. Or, you can fix and make a pull request.

optimistex avatar Oct 28 '18 11:10 optimistex

I know this is old, but for anyone searching for an answer, hopefully this might help.

In my case I was working with a co-worker and she was able to re-produce the error. Our solution was to change the order so that the defaultValue attribute was positioned prior to the [(ngModel)].

In other words, the order of the html attributes affected whether or not we were getting this error and the defaultValue attribute had to be placed prior to the [(ngModel)] attribute for things to work.

lkspencer avatar Oct 23 '19 21:10 lkspencer

I know this is old, but for anyone searching for an answer, hopefully this might help.

In my case I was working with a co-worker and she was able to re-produce the error. Our solution was to change the order so that the defaultValue attribute was positioned prior to the [(ngModel)].

In other words, the order of the html attributes affected whether or not we were getting this error and the defaultValue attribute had to be placed prior to the [(ngModel)] attribute for things to work.

Can confirm - I moved the [defaultValue] to before [(ngModel)] and the error of 'ExpressionChangedAfterItHasBeenCheckedError' went away.

dpollock avatar Dec 04 '20 18:12 dpollock