1
votes

Angular 6/7: ne récupérez les données de l'API qu'une seule fois, mais affichez-les dans deux routes / vues

Je suis nouveau dans Angular > v1 et j'essaie de comprendre certains concepts (venant d'un arrière-plan React / Redux).

J'ai une API RESTful que je veux obtenir données de l'API et affichez-les dans la vue / route # 1, puis autorisez l'utilisateur à explorer et voir plus d'informations dans la vue / route # 2 (en utilisant .filter () pour obtenir uniquement les informations pertinentes objet).

Cependant, je trouve qu'Angular télécharge les données de l'API à chaque changement de vue / route. Comment contourner cela normalement, contourner ce problème ou y a-t-il un modèle différent que les développeurs angulaires utilisent habituellement?

// src/app/components/domain-detail/domain-detail.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { ApiClientService } from '../../core/api-client.service';

@Component({
  selector: 'app-domain-detail',
  templateUrl: './domain-detail.component.html',
  styleUrls: ['./domain-detail.component.scss']
})
export class DomainDetailComponent implements OnInit, OnDestroy {
  domainUuid: any;
  domains: any;
  private sub: any;

  constructor(
    private ApiClient: ApiClientService,
    private route: ActivatedRoute
  ) {}

  ngOnInit() {
    // my attempt at caching (still unfamiliar with Rxjs)
    this.sub = this.route.params.subscribe(params => {
      this.domainUuid = params.uuid;
    });
    this.ApiClient.getDomains().subscribe(data => this.domains = data.filter(item => item.uuid === this.domainUuid));
  }

  ngOnDestroy() {
    this.sub.unsubscribe();
  }

}

// src/app/components/domains-list/domains-list.component.ts

import { Component, OnInit } from '@angular/core';
import { ApiClientService} from '../../core/api-client.service';

@Component({
  selector: 'app-domains-list',
  templateUrl: './domains-list.component.html',
  styleUrls: ['./domains-list.component.scss']
})
export class DomainsListComponent implements OnInit {

  domains: any;

  constructor(private ApiClient: ApiClientService) {}

  ngOnInit() {
    this.ApiClient.getDomains().subscribe(data => this.domains = data);
  }

}

// src/app/core/api-client.service.ts

import { Injectable } from '@angular/core';
import { HttpClient  } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class ApiClientService {

  domains;

  constructor(private http: HttpClient) { }

  getDomains() {
    console.info(this.domains);
    if (this.domains && this.domains.length) {
      return this.domains;
    }
    this.domains = this.http.get<Array<any>>('http://192.168.33.11:3000/domains/list');
    return this.domains;
  }

  getHostCapabilities() {
    return this.http.get<Array<any>>('http://192.168.33.11:3000/host/capabilities');
  }
}


3 commentaires

D'après votre code, il semble que vous appelez this.ApiClient.getDomains () dans les deux composants mentionnés, c'est pourquoi il appelle l'API lors du changement de route.


Oui, cela je comprends mais comment aborder ceci et ne pas faire cela? À quoi ressemble ce modèle? C'est tout ce que j'ai vu documenté


Si vous souhaitez que this.domains (domaines) soit disponible sur chaque composant, vous devez utiliser un service pour partager les données entre les composants. blogs.msmvps.com/deborahk/…


3 Réponses :


1
votes

Vous pouvez utiliser shareReplay (1) pour partager les dernières données avec les nouveaux abonnés. Mais d'après ce que j'ai compris de votre code, vous ne souhaitez charger les domaines qu'une seule fois. Par conséquent, vous pouvez appeler la requête http sur le constructeur du service, puis partager les données avec des domaines observables comme ceci:

import { Injectable } from '@angular/core';
import { HttpClient  } from '@angular/common/http';
import {Observable} from 'rxjs';
import {shareReplay} from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class ApiClientService {

  domains: Observable<Array<any>>;

  constructor(private http: HttpClient) { 
     this.domains = this.http.get<Array<any>>('http://192.168.33.11:3000/domains/list');
  }

  getDomains() {
    return this.domains.pipe(shareReplay(1));
  }

  getHostCapabilities() {
    return this.http.get<Array<any>>('http://192.168.33.11:3000/host/capabilities');
  }
}


2 commentaires

Une excellente solution lorsque vous ne voulez pas d'un magasin entier.


@MarzSocks heureux d'apprendre que cela a aidé. Btw, avec votre réponse, j'ai remarqué une faute de frappe dans la réponse: D



0
votes

Stockez les données dans le stockage local du navigateur après les avoir reçues dans le premier itinéraire. Utilisez ensuite ces données de stockage local dans les itinéraires suivants. (Oui, il existe un risque de sécurité.)


0 commentaires

0
votes

Vous pouvez utiliser @ ngrx / store. C'est l'implémentation de Redux pour Angular.


0 commentaires