Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 Change Detection Infinite Loop

We have a simple component with an input property as such:

<app-example [exampleInput$]="exampleInputData$"></app-example>

On the component where we use app-example we have:

get exampleInputData$(): any {
    var subject = new Subject<string>();
    console.log("Log1");

    this.exampleService.getAllData(this.id).subscribe(data => {
      console.log("Log2");
      subject.next(data);
    });

    return subject.asObservable();
  }

And the exampleService is a simple observable as such:

public getAllData(id): Observable<ExampleObject[]> {
    return this.http.get(`${this.baseUrl}data/${id}`).map((response: Response) => {
      var data = <ExampleObject[]>response.json();
      return data;
    }).catch(this.handleError);
  }

When we run this it get's into an infinite loop, if we change the changeDetection to OnPush it stops or if we remove the call to getAllData. Does anyone have an idea of why this is causing an infinite loop?

Below is the app-example component and the HTML template:

export class ExampleComponent implements OnDestroy {      
  private subscription: ISubscription;
  private parsedResponse : any;

  @Input() exampleInput$;

  getData(): void
  {    
    this.subscription = this.exampleInput$.subscribe((data) => {this.parsedResponse = data;},
      () => {
        // Here we download the data as CSV
      });
  }

  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }

Template:

<button class="btn btn-primary" (click)="getData()">
  Download As CSV
</button>
like image 855
user351711 Avatar asked Oct 19 '25 11:10

user351711


1 Answers

You are binding a method in the HTML. So in every change detection the method will be invoked. You need to set the observable like an attribute and the content in the exampleInputData$() put it in ngOnInit

export AppComponent {

    subject = new Subject<string>();
    observable$ = subject.asObservable();
    id: number;

    ngOnInit() {
        // I expected you know how to get the id value
        this.exampleService.getAllData(this.id).subscribe(data => {
            this.subject.next(data);
        });
    }
}

And the HTML

<app-example [exampleInput$]="observable$"></app-example>
like image 125
Alan Grosz Avatar answered Oct 21 '25 02:10

Alan Grosz