Маршрут queryParam, требующий два события и определяющий «глобальную» переменную Onit - PullRequest
0 голосов
/ 09 марта 2020

Мое приложение использует службу и отдельный компонент следующим образом:

data.service.ts - эта служба «получает» ответы от двух различных вызовов API и передает сохраненный запрос маршрута параметр (id из маршрута) для одного из URL-адресов API:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';
import { course } from './shared/course';

@Injectable({
  providedIn: 'root'
})
export class DataService {
url_json = 'api url'
url_course = 'api url'

constructor(private http: HttpClient) { }

getMenus() {
  return this.http.get(this.url_course)
}
getContent(id): Observable<course> {
  return this.http.get<course>(this.url_json + '/' + id) //this id comes from the route
}
}

nav.component.ts - этот компонент выполняет следующие действия:

  1. подписывается на ответ API api для отображения 5 компонентов меню
  2. подписывается на ответ API api для отображения содержимого, связанного с каждым элементом меню, и будет отображаться при нажатии каждого элемента меню.
  3. подписывается на параметр запроса, который также служит идентификатором, используемым в одном из остальных вызовов API

      import { Component, OnInit } from '@angular/core';
      import { DataService } from '../data.service';
      import { RouterLink, Router, Params, ActivatedRoute } from '@angular/router';
    
      @Component({
      selector: 'app-nav',
      templateUrl: './nav.component.html',
      styleUrls: ['./nav.component.css']
      })
    
     export class NavComponent implements OnInit {
    
     //iterables for holding data
     menus;
     id;
     content;
    
     // Query parameters 
     queryParams: Params;
    
     constructor(private data: DataService, private route: ActivatedRoute) { }
    
     ngOnInit(){
      this.data.getMenus().subscribe((data: {})=> this.menus = data);
      this.route.queryParams.subscribe(params => this.id = params.id)
      }
      get_id(id){
      this.data.getContent(this.id).subscribe((response: {})=> this.content = response)
      console.log(id + ' from nav')
     }
     }
    

nav.component. html - маршрут назначает идентификатор индекса как queryParam, а get_id (id) передает значение идентификатора обратно компоненту nav, где оно сохраняется для использования с конечной точкой вызова rest.

<div *ngFor="let menu of menus; index as id">
    <ul>
        <li><a routerLink = "" [queryParams]="{id: id}" (click)="get_id(id)">{{menu['lessonName']}}</a></li>
    </ul>
</div>
<div *ngIf="content">
{{content.id}}
</div>

Проблема: все работает как требуется, за исключением двух небольших ошибок и Мне нужен совет или соображения по поводу возможной проблемы:

  1. Идентификатор не определен при загрузке приложения, поскольку ни одна из ссылок еще не была нажата, а параметры запроса не переданы. Как я могу установить идентификатор с начальным значением, чтобы предотвратить это, но все же позволить ему обновлять его новым значением, когда пользователь нажимает на ссылку меню и параметр запроса сохраняется?

  2. Это может быть связано с первой проблемой - каждую ссылку нужно щелкнуть дважды, чтобы обновить запрос и содержимое. Каждая ссылка на 1 клик «меньше», чем значение параметра запроса, которое должно быть назначено при первом клике. Повторное нажатие обновляет значение и связанный контент по мере необходимости.

Спасибо за вашу помощь.

1 Ответ

0 голосов
/ 09 марта 2020

Вы хотите делать запросы API на основе параметра маршрута. Это просто случай цепочки вызова API к наблюдаемому маршруту.

route.queryParams - это Subject, который выдает новое значение при изменении параметров запроса. И поскольку он реализован с BehaviorSubject, это означает, что вы также получаете начальное значение.

Все, что зависит от параметров запроса, должно быть приковано к queryParams, наблюдаемому с switchMap.

export class NavComponent implements OnInit {

  //iterables for holding data
  menus;
  content;

  constructor(private data: DataService, private route: ActivatedRoute) { }

  ngOnInit(){
    this.data.getMenus().subscribe((data: {}) => this.menus = data);
    this.route.queryParams.pipe(
      switchMap(params => this.data.getContent(params.id))
    ).subscribe((response: {}) => {
      this.content = response;
    });
  }
}

И поскольку ваш компонент теперь заботится о вызове службы при изменении параметров запроса, вам не нужно вызывать его из HTML.

<div *ngFor="let menu of menus; index as id">
  <ul>
    <li>
      <a routerLink = "" [queryParams]="{id: id}">
        {{menu['lessonName']}}
      </a>
    </li>
  </ul>
</div>
<div *ngIf="content">
  {{content.id}}
</div>

Так что теперь поток событий:

  • 1a. Загрузить меню
  • 1b. Загрузка содержимого на основе начального параметра запроса
  • Пользователь нажимает на ссылку меню
  • Обновлены параметры запроса
  • Ваш switchMap выполняет новый сервисный вызов с последним параметром запроса

1a и 1b не синхронизированы, но они, кажется, независимы друг от друга, поэтому сейчас это не проблема.

Обычно вы должны были бы отказаться от подписки на темы, но маршрутизатор - это особый случай, который убирает после себя, поэтому вам не нужно отписываться вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...