question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Issue saying Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '50'. Current value: '50'

See original GitHub issue

Can see a reason for this or a way to correct It

component html

<div class="slider"
     [ngClass]="[class, direction]"
     (mousedown)="dragStart($event)"
     #sliderElementTemplate
>
  <div class="sliderTrack {{ class }}"></div>
  <div class="sliderThumb {{ class }} noTransition">{{ val }}</div>
  <input type="hidden" name="{{ input }}]" id="{{ input }}" value="{{ val }}">
</div>

TS

import {AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core';

@Component({
  selector: 'app-slider',
  templateUrl: './slider.component.html',
  styleUrls: ['./slider.component.css']
})
export class SliderComponent implements OnInit, AfterViewInit {
  private xOffset: any;
  private yOffset: any;

  @Input() min;
  @Input() max;
  @Input() val;
  @Input() input;
  @Input() steps;
  @Input() callBack;
  @Input() direction;
  @Input() inverted;
  @Input() class;

  @ViewChild('sliderElementTemplate') sliderElement;

  private dragging: boolean;
  private sliderTrack: any;
  private sliderThumb: any;

  constructor() {
  }

  ngOnInit() {
  }

  ngAfterViewInit() {
    this.sliderElement = this.sliderElement.nativeElement;
    this.sliderTrack = this.sliderElement.childNodes[0];
    this.sliderThumb = this.sliderElement.childNodes[1];
    this.setThumbPos();
  }

  setThumbPos() {
    this.sliderThumb.classList.add('noTransition');
    const range = this.max - this.min;
    const correctedStartValue = this.val - this.min;
    let percent = (correctedStartValue * 100) / range;

    if (this.inverted) {
      percent = 100 - percent;
    }

    if (this.direction === 'vertical') {
      this.sliderThumb.style.top = 'calc(' + percent + '% - ' + (this.sliderThumb.offsetHeight / 100 * percent) + 'px)';
    } else {
      this.sliderThumb.style.left = 'calc(' + percent + '% - ' + (this.sliderThumb.offsetWidth / 100 * percent) + 'px)';
    }
    const points = this.precision(this.steps);

    this.val = (Math.floor(this.val / this.steps) * this.steps).toFixed(points);

    this.sliderThumb.innerHTML = this.val;
    setTimeout(() => {
      this.sliderThumb.classList.remove('noTransition');
    }, 300);
  }

  dragStart(event) {
    this.xOffset = this.sliderElement.offsetLeft;
    this.yOffset = this.sliderElement.offsetTop;
    this.sliderThumb.classList.add('noTransition');
    if (event.target.className.indexOf('sliderTrack') !== -1) {
      this.sliderThumb.classList.remove('noTransition');
      this.dragging = true;
      this.dragGo(event);
    }
    this.dragging = true;

    // tslint:disable-next-line:no-shadowed-variable
    document.addEventListener('mousemove', (event) => {
      this.dragGo(event);
    });
    // tslint:disable-next-line:no-shadowed-variable
    document.addEventListener('mouseup', (event) => {
      this.dragStop(event);
    });

  }

  dragGo(event) {
    if (this.dragging) {

      let x = event.x || event.pageX;
      let y = event.y || event.pageY;

      x = x - (this.sliderThumb.offsetWidth / 2);
      y = y - (this.sliderThumb.offsetHeight / 2);

      if (x - this.xOffset < 0) {
        x = 0;
      }
      if (y - this.yOffset < 0) {
        y = 0;
      }

      if (x - this.xOffset > this.sliderElement.offsetWidth - this.sliderThumb.offsetWidth) {
        x = this.xOffset + this.sliderElement.offsetWidth - this.sliderThumb.offsetWidth;
      }

      if (y - this.yOffset > this.sliderElement.offsetHeight - this.sliderThumb.offsetHeight) {
        y = this.yOffset + this.sliderElement.offsetHeight - this.sliderThumb.offsetHeight;
      }

      if (this.direction === 'vertical') {
        const percent = (y - this.yOffset) / (this.sliderElement.offsetHeight - this.sliderThumb.offsetHeight) * 100;

        const val = (percent * (this.max - this.min) / 100) + this.min;

        const points = this.precision(this.steps);
        if (this.inverted === true) {
          this.val = ((this.max + this.min) - (Math.floor(val / this.steps) * this.steps)).toFixed(points);
        } else {
          this.val = (Math.floor(val / this.steps) * this.steps).toFixed(points);
        }

        this.sliderThumb.style.top = 'calc(' + percent + '% - ' + (this.sliderThumb.offsetHeight / 100 * percent) + 'px)';
      } else {
        const percent = (x - this.xOffset) / (this.sliderElement.offsetWidth - this.sliderThumb.offsetWidth) * 100;

        const val = (percent * (this.max - this.min) / 100) + this.min;

        const points = this.precision(this.steps);
        if (this.inverted === true) {
          this.val = ((this.max + this.min) - (Math.floor(val / this.steps) * this.steps)).toFixed(points);
        } else {
          this.val = (Math.floor(val / this.steps) * this.steps).toFixed(points);
        }

        this.sliderThumb.style.left = 'calc(' + percent + '% - ' + (this.sliderThumb.offsetWidth / 100 * percent) + 'px)';
      }

      this.sliderThumb.innerHTML = this.val;
    }
  }

  dragStop(event) {
    this.dragging = false;
  }

  precision(a) {
    if (!isFinite(a)) {
      return 0;
    }
    let e = 1;
    let p = 0;
    while (Math.round(a * e) / e !== a) {
      e *= 10;
      p++;
    }
    return p;
  }
}
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '50'. Current value: '50'.
throwErrorIfNoChangesMode — core.js:8290
bindingUpdated — core.js:21606
interpolation1 — core.js:21738
ɵɵtextInterpolate1 — core.js:25007
ɵɵtextInterpolate — core.js:24978
SliderComponent_Template — slider.component.html:7
executeTemplate — core.js:13942
refreshView — core.js:13801
refreshComponent — core.js:15166
refreshChildComponents — core.js:13535
refreshView — core.js:13855
refreshComponent — core.js:15166
refreshChildComponents — core.js:13535
refreshView — core.js:13855
refreshComponent — core.js:15166
refreshChildComponents — core.js:13535
refreshView — core.js:13855
renderComponentOrTemplate — core.js:13916
tickRootContext — core.js:15330
detectChangesInRootView — core.js:15365
checkNoChangesInRootView — core.js:15395
checkNoChanges — core.js:16958
tick — core.js:42792
_loadComponent — core.js:42838
bootstrap — core.js:42764
forEach
_moduleDoBootstrap — core.js:42352
(anonymous function) — core.js:42307
onInvoke — core.js:41362
run — zone-evergreen.js:124
(anonymous function) — zone-evergreen.js:851
onInvokeTask — core.js:41340
runTask — zone-evergreen.js:168
drainMicroTaskQueue — zone-evergreen.js:570
promiseReactionJob

version

Angular: 9.0.0-rc.4
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router, service-worker
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.0-rc.4
@angular-devkit/build-angular     0.900.0-rc.4
@angular-devkit/build-optimizer   0.900.0-rc.4
@angular-devkit/build-webpack     0.900.0-rc.4
@angular-devkit/core              9.0.0-rc.4
@angular-devkit/schematics        9.0.0-rc.4
@angular/cdk                      8.2.3
@angular/pwa                      0.803.19
@ngtools/webpack                  9.0.0-rc.4
@schematics/angular               9.0.0-rc.4
@schematics/update                0.900.0-rc.4
rxjs                              6.5.3
typescript                        3.6.4
webpack                           4.41.2

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:8

github_iconTop GitHub Comments

1reaction
neofuturecommented, Dec 9, 2019

I see you have to make the component for change detection cheers both

1reaction
tomicarsk6commented, Dec 9, 2019

More about different mechanisms that you can use to trigger change detection you can read it here:

Link: https://netbasal.com/a-comprehensive-guide-to-angular-onpush-change-detection-strategy-5bac493074a4

Read more comments on GitHub >

github_iconTop Results From Across the Web

ExpressionChangedAfterItHasBe...
ERROR : ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'mat-checkbox-checked': ...
Read more >
NG0100: Expression has changed after it was checked - Angular
Angular throws an ExpressionChangedAfterItHasBeenCheckedError when an expression value has been changed after change detection has completed.
Read more >
Angular Debugging "Expression has changed": Explanation ...
Learn a complete explanation about ExpressionChangedAfterItHasBeenCheckedError: why it occurs, how to troubleshoot it and how to fix it.
Read more >
Expression Has Changed After It Was Checked — Angular ...
Error : ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'A message for the child component'.
Read more >
The Last Guide For Angular Change Detection You'll Ever Need
This detector compares the current value with the previous value of the property. If the value has changed it will set isChanged to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found