title: Prevent duplicate HTTP requests in Angular 2 API-driven tree-view
body: <p>I have an Angular 2 app which calls a JSON API to load data into a nested HTML list (<code>&lt;ol&gt;</code>).  Essentially a dynamically generated tree-view.  Since the data-set from the API will eventually become very large the tree is populated progressively when the user opens a branch (user opens a branch, the API is called with the id of the node which has been opened, the API returns a JSON feed of the direct children of than node, Angular binds the returned JSON to some new HTML <code>&lt;li&gt;</code> elements and the tree expands to show the new branch).</p>
  
  <p>You can see it in action in this <a href="http://plnkr.co/edit/100nwxwXuCONelmHUTF4?p=preview" rel="noreferrer">Plunkr</a>.  It uses a recursive directive and works nicely.  <em>Currently, because I can't open the actual API up to public requests, it's just calling a static JSON feed, hence the returned data for each of the nodes is just repeated, but hopefully you get the idea.</em></p>
  
  <p>The issue I'm now seeking to overcome is to prevent extraneous HTTP calls when a branch is closed and then re-opened.  Having read the <a href="https://angular.io/docs/ts/latest/guide/server-communication.html#!#rxjs" rel="noreferrer">HTTP client docs</a> I was hoping that this would be as simple as modifying the method which subscribes to the data service to chain the <code>.distinctUntilChanged()</code> method to the <code>app/content-list.component.ts</code> file, as follows:</p>
  
  <pre><code>getContentNodes() {
      this._contentService.getContentNodes(this._startNodeId)
          .distinctUntilChanged()
          .subscribe(
              contentNodes =&gt; this.contentNodes = contentNodes,
              error =&gt;  this.errorMessage = &lt;any&gt;error
          );
  }
  </code></pre>
  
  <p>However, when I open up the browser network inspector, it still makes a call to the API each time the same tree branch is re-opened.</p>
  
  <p>Could anyone advise how to resolve this?</p>
  
  <p>Many thanks.</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>I'm trying to implement @Thierry Templier's answer below; caching the data returned by the API. So the content service is now:</p>
  
  <pre><code>import {Injectable}                 from 'angular2/core';
  import {Http, Response}             from 'angular2/http';
  import {Headers, RequestOptions}    from 'angular2/http';
  import {ContentNode}                from './content-node';
  import {Observable}                 from 'rxjs/Observable';
  
  @Injectable()
  export class ContentService {
      constructor (private http: Http) {}
  
      private _contentNodesUrl = 'app/content.json';
  
      _cachedData: ContentNode[];
  
      getContentNodes (parentId:number) {
          if (this._cachedData) {
              return Observable.of(this._cachedData);
          } else {
              return this.http.get(this._contentNodesUrl + parentId)
                  .map(res =&gt; &lt;ContentNode[]&gt; res.json())
                  .do(
                      (data) =&gt; {
                      this._cachedData = data;
                  })
                  .catch(this.handleError);
          }
      }
  
      private handleError (error: Response) {
          console.error(error);
          return Observable.throw(error.json().error || 'Server error');
      }
  }
  </code></pre>
  
  <p>However, what's happening here is that when the page loads, <code>this._cachedData</code> is returning false and the API call is firing and populating <code>this._cachedData</code> with the returned value (<code>data</code>), which is correct. However, when the tree node is opened in the web page UI, the following line is run repeatedly thousands of times until eventually the browser crashes:</p>
  
  <pre><code>return Observable.of(this._cachedData);
  </code></pre>
  
  <p>I'm still very much at the beginning when it comes to Angular 2, so would really appreciate any pointers as to why this isn't working to help my learning.</p>