Angular 6/7: только один раз получить данные из API, но отобразить их в двух маршрутах / видах - PullRequest
0 голосов
/ 06 января 2019

Я новичок в Angular > v1 и пытаюсь разобраться в некоторых концепциях (происходящих из фона React / Redux).

У меня есть RESTful API. Я хочу получить данные из API и отобразить их в представлении / маршруте № 1, затем разрешить пользователю выполнить детализацию и просмотреть дополнительную информацию в представлении / маршруте № 2 (используя .filter() для получить только соответствующий объект).

Однако я обнаружил, что Angular загружает данные API при каждом изменении вида / маршрута. Как вы обходите это нормально, вы обходите это или есть другой шаблон, который обычно используют разработчики Angular?

// 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');
  }
}

// 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/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();
  }

}

Ответы [ 3 ]

0 голосов
/ 06 января 2019

Храните данные в локальном хранилище браузера после получения их по первому маршруту. Затем используйте данные локального хранилища в следующих маршрутах. (Да, существует угроза безопасности.)

0 голосов
/ 07 января 2019

Вы можете использовать @ ngrx / store. Это реализация Redux для Angular.

0 голосов
/ 06 января 2019

Вы можете использовать shareReplay(1), чтобы поделиться последними данными с новыми подписчиками. Но из того, что я понимаю из вашего кода, вы хотите загрузить домены только один раз. Таким образом, вы можете вызвать http-запрос на конструктор службы, а затем поделиться данными с domains, наблюдаемым следующим образом:

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.observable = 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');
  }
}
...