zgrybus zgrybus - 17 days ago 7
Javascript Question

Angular2 SliderShow

I want to build slider in angular2, but i have a lot of trouble with it. Ok, let's go to main problem. Why is this function getting me this error

"ERROR Error: Uncaught (in promise): RangeError: Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded"


This is my code ( i have tried a lot of things with ViewChild etc, now stuck at this problem ).

import { Component, OnInit, AfterViewInit, Input, ViewChild }

from '@angular/core';

@Component({
selector: 'slider',
template: `
<div class="slider-container">
<header>
<div class="slider-information">
<span class="slider-information--title" id="slidername">Acer C720-2103 Chromebook</span>
<span class="slider-information--category">
Category: <span id="slidercategory">Laptops</span>
</span>
<span class="slider-information--learnmore">
More about <span id="sliderinfoname">Acer C720-2103 Chromebook</span>
</span>
</div>
<div class="slider-image">
<img id="sliderimage" src="../../../images/slider/laptop-slider.jpg" alt="Laptop">
</div>
</header>
</div>
`,
styles: [`
:host{
overflow: hidden;
}
`]
})
export class SliderComponent implements OnInit, AfterViewInit {
sliderCount: number = 0;
images: any[];
constructor() { }
ngOnInit() {
this.images = this.createImages();
}
ngAfterViewInit() {
this.slider();
}
slider(): void{
var slidername = document.getElementById('slidername');
var sliderimage = document.getElementById('sliderimage');
var sliderinfoname = document.getElementById('sliderinfoname');
var slidercategory = document.getElementById('slidercategory');
if(this.sliderCount > this.images.length - 1){
this.sliderCount = 0;
}
slidername.innerHTML = this.images[this.sliderCount].name;
sliderimage.setAttribute('src', this.images[this.sliderCount].url);
sliderinfoname.innerHTML = this.images[this.sliderCount].name;
slidercategory.innerHTML = this.images[this.sliderCount].category;
this.sliderCount += 1;
debugger;
setTimeout(this.slider(), 2000);
}
createImages(): any[]{
var newImages: any[];
newImages = [
{ url: "../../../images/slider/laptop-slider.jpg", category: "Laptop" , name: "Acer C720-2103 Chromebook" },
{ url: "../../../images/slider/mobilephone-slider.jpg", category: "Phone", name: "Samsung Edge S6" }
]
return newImages;
}
}


What is the problem?

UPDATE

I changed this
setTimeout(this.slider(), 2000);
to
setTimeout(this.slider, 2000);
. It works only in first iternation. In second i am getting "ERROR TypeError: Cannot read property 'length' of undefined"

Answer

First you were calling

this.slider() from within this.slider() because you were calling it instead of passing a reference to this.slider, that was causing a stack overflow.

Now you are passing a reference that doesn't have this correctly bound. Change it to

setTimeout(() => this.slider(), 2000);

That will run this.slider() after 2 secs with this correctly set. See How to access the correct `this` inside a callback?

If you are calling document.getElementById(), you are not doing things as Angular would have you. That data you are digging out of the DOM should be passed to your component instead of tightly coupling your component to the environment.