Angular Заполнить mat-optgroup / mat-options от 2 различных веб-сервисов - PullRequest
0 голосов
/ 29 августа 2018

Я новичок в Angular и пытаюсь добавить выбор матов с группами опций в мое приложение Angualr 6. У меня есть существующий веб-API, который имеет 2 URL-адреса. Один URL возвращает группы, другой возвращает элементы в каждой группе с заданным идентификатором группы.

Эта страница переходит в бесконечный цикл при загрузке. Для устранения неполадок я попытался добавить регистратор для this.groups в ngOnInit (), чтобы я мог создать массив, который использует HTML, но похоже, что this.groups / this.items не инициализируются до тех пор, пока HTML-страница не вызывается.

Я, должно быть, подхожу к этому неправильно. Я только пытаюсь добавить HTML mat-select, где mat-optgroups определяются 1 веб-сервисом / опции mat определены другим веб-сервисом.

Я построил это на основе этого примера (https://material.angular.io/components/select/overview#creating-groups-of-options):

navigation.component.ts

import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import {HttpErrorResponse} from '@angular/common/http';
import {Component, OnInit} from '@angular/core';
import { Group } from '../group';
import { GroupService } from '../group.service';
import { Item } from '../item';
import { ItemService } from '../item.service';

@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.css']
})
export class NavigationComponent implements OnInit {

  groups: Group [] = [];
  items: Item [] = [];
  pokemonControl = new FormControl();


  constructor(private groupService: GroupService, private itemService: ItemService) {}


  ngOnInit () {
    this.getGroups();
    console.log("length: " + this.groups.length); // logs 0 as length
  }

  getGroups(): void {
    this.groupService.getGroups().subscribe(
      data => {
        this.groups = data as Group[];
        console.log(data);
      },
      (err: HttpErrorResponse) => {
        console.log (err.message);
      }
    );

  }

  getItems(department: number): void {
    this.itemService.getItems(department).subscribe(
      data => {
        this.items = data as Item[];
        console.log(data);
      },
      (err: HttpErrorResponse) => {
        console.log (err.message);
      }
    );
  }

}

group.service.ts

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

import { Observable, of } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';

import { Group } from './group';

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

  private groupsUrl = 'http://localhost:8180';

  constructor(private http: HttpClient) { }

   getGroups (): Observable<Group[]> {
    const url = `${this.groupsUrl}/groups`;
    return this.http.get<Group[]>(url);
  }

  private handleError<T> (operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
    console.error(error);
    console.log(`${operation} failed: ${error.message}`);
    return of(result as T);
    };
  }

}

item.service.ts

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

import { Observable, of } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';

import { Item } from './item';

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

  private itemsUrl = 'http://localhost:8180';

  constructor(
    private http: HttpClient) { }


   getItems (groupId: number): Observable<Item[]> {
    const url = `${this.itemsUrl}/groups/${groupId}/items`;
    return this.http.get<Item[]>(url);
  }

  private handleError<T> (operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
      console.error(error);
      console.log(`${operation} failed: ${error.message}`);
      return of(result as T);
    };
  }

}

HTML

<mat-select [formControl]="pokemonControl">
  <mat-optgroup *ngFor="let group of group.groupList" [label]="group.groupName"
                [disabled]="group.disabled">
    <mat-option *ngFor="let item of getItems(group.groupId).itemList" [value]="item.itemId">
      {{item.itemName}}
    </mat-option>
  </mat-optgroup>
</mat-select>

1 Ответ

0 голосов
/ 29 августа 2018

Проверьте эту строку:

let item of getItems(group.groupId).itemList

Эта инструкция находится внутри другого *ngFor, поэтому она выполняется столько раз, сколько длина group.groupList.

Если длина составляет 10 элементов, методы getItems(...) будут вызываться 10 раз, и каждый раз он будет выдавать HTTPRequest и после асинхронного ответа будет перезаписывать переменную items .

Таким образом, поведение непредсказуемо, и переменная items не может быть использована, так как она меняется несколько раз за несколько секунд. То, что вы говорите, испытывая как бесконечные циклы, скорее всего, это просто обнаружение изменений, которое реагирует на новое изменение, производящее новое изменение.

Решение:

Не подписывайте несколько наблюдаемых, если вам нужно использовать их синхронно!

Наблюдаемые являются асинхронными. Вы не можете догадаться, когда он выполнит код подписки, который является заказом или всякий раз, когда будет.

Rxjs предоставляет несколько операторов для решения этой проблемы. Вы можете проверить операторы объединения здесь .

...