Search code examples
angulartypescriptrxjslodash

Angular Joining Two Arrays and Displaying Them as a Categorized List


In my code, I call two json objects using fromFetch method. I can get them separately and display them as an array on the console. The categoryId of the items$ is the same with the id of categories$. I want to join them and, display them as a single array by grouping them by category$.name. I tried the approach below but it didn't work, what should I do to achieve this? TS:

items$: Observable<Item[]>;
  categories$: Observable<Category[]>;
  dataSource: MatTableDataSource<Item>;

  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
  @ViewChild(MatSort, { static: true }) sort: MatSort;

  displayedColumns: string[] = ['categoryId', 'name', 'quantityPerUnit'];

  ngAfterViewInit(): void {
    this.items$ = fromFetch(
      'https:items.json'
    ).pipe(
      switchMap((response) => {
        return response.json();
      })
    );

    this.items$.subscribe(function (result) {
      const grouped = _.groupBy(result, (res) => res.categoryId);
      this.dataSource = result;
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
      console.log(grouped);
    });

    this.categories$ = fromFetch(
      'https:categories.json'
    ).pipe(
      switchMap((response) => {
        return response.json();
      })
    );

    this.categories$.subscribe(function (data) {
      // const categoryGrouped = _.groupBy(result, (res) => res.name);
      console.log(data);
    });

    var merged = _.merge(_.keyBy(this.items$, 'categoryId'), _.keyBy(this.categories$, 'id'));
    var values = _.values(merged);
    console.log(values);
  }

Solution

  • No lodash version. You can also do a clone deep of loadash, so that there are no reference errors. like shown below.

    let output = cloneDeep(element);

    We need to do forkJoin to get both the api calls and merge them!

    @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
    @ViewChild(MatSort, { static: true }) sort: MatSort;
    
    displayedColumns: string[] = ['categoryId', 'name', 'quantityPerUnit'];
    
    ngAfterViewInit(): void {
        this.items$ = fromFetch('https:items.json').pipe(
            switchMap(response => {
                return response.json();
            })
        );
    
        this.categories$ = fromFetch('https:categories.json').pipe(
            switchMap(response => {
                return response.json();
            })
        );
        forkJoin([this.items$, this.categories$]).subscribe(([items, categories]: Array<any>) => {
            const finalArray: Array<any>= [];
            items.forEach((element: any) => {
                let output = {...element};
                const foundCategory = categories.find(x => x.categoryId === element.categoryId);
                if(foundCategory) {
                    output = {...output, ...foundCategory};
                }
                finalArray.push(output);
            });
            this.dataSource = finalArray;
            this.dataSource.paginator = this.paginator;
            this.dataSource.sort = this.sort;
        });
    }