Угловая древовидная структура с 2 различными списками, пополняемыми из вложенной подписки rxjs - PullRequest
1 голос
/ 30 мая 2019

В Angular 7 у меня есть два наблюдаемых, которые получают данные с сервера;Observables дает следующие списки:

    productgroup = [{"id":"1","groupname":"gr1"},{"id":"2","groupname":"gr2"}];
    products = [{"id":"1","productname":"COMPUTER","productgroup":"gr2",....},{"id":"2","productname":"ACCESSORIES","productgroup":"gr1",....}]

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

    [
        {
            "id":1,
            "name": "gr1",
            "children": [
                {"id":"1","productname":"COMPUTER","productgroup":"gr2",....},
                {"id":"2","productname":"ACCESSORIES","productgroup":"gr1",....}
            ]
        }
        {
        }
    ]

Код, который я пробовалвыглядит следующим образом -

 this.productGroupService.getAll().pipe(switchMap((allgroup: any) => {
          var flag = 0;
          this.groups = []; // array to hold group or parent data
          allgroup.map(element => {
            this.finalarr = []; // fial array 
            console.log(element.id);

            this.productService.getbygroup(element.id)// for each group getting product data list
            .pipe(map((data) => {
              this.productInGroup[flag] = []; // array to hold children data
              this.groups.push(element);
              data.map((dval)=>{
                this.productInGroup[flag].push({productname: dval["productname"], id: String(dval["id"])});
              })
              flag++;

            })
            ).subscribe((data) => {
              if(allgroup.length == flag){
                //console.log(this.groups);
                var flag2 = 0;
                this.groups.map(()=>{
                  var obj = {groupname: this.groups[flag2].groupname,id:this.groups[flag2].id,
                    products:this.productInGroup[flag2]}; // joining child and parent data into single object
                  this.finalarr.push(obj);
                  flag2++;
                  if(flag2 == this.groups.length){
                    this.datasource = this.finalarr;
                    console.log(this.datasource);
                  }
                })
              }
            })
          });
      })).subscribe()

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

Код работает для небольшого набора данных.Но я не доволен этим решением, поскольку оно перебирает все продукты для всех групп nxm раз.

Я знаю, что было бы намного проще, если бы таблица в базе данных была связана с внешним ключом и простым списком, но я не могу это контролировать.

Любая помощь или предложениеappriciated.Спасибо!

1 Ответ

1 голос
/ 31 мая 2019

С введением состояния ваше решение стало очень сложным.

Попробуйте это

  const productGroup$ = this.productGroupService.getAll();

  productGroup$.pipe(
  mergeMap((productGroupArray) => from(productGroupArray)),
  concatMap(
    (productGroupItem) => this.productService.getbygroup(productGroupItem.id).pipe(
    map((product) => {
      let json = {};
      json['id'] = productGroupItem.id;
      json['name'] = productGroupItem.groupname;
      json['children'] = product;
      return json;
    })
  )),
  toArray()
).subscribe((val) => console.log(val));

Внутри подписки вы получите массив напрямую.

...