ANGULAR 17:有人可以帮我解决 Angular 17 中的 @for 循环问题吗?

问题描述 投票:0回答:1

背景:

Angular 17 应用程序连接到后端的 ExpressJS 应用程序。

Angular 应用程序组件:

  • 卡片项目
  • 列表项
  • 其他不相关

服务:

  • 类别:
export class CategoriesService {

    private baseUrl = 'http://localhost:3000/api/categories';

    private httpClient = inject(HttpClient);

    async getAll() {
        return firstValueFrom(
            this.httpClient.get<Category[]>(this.baseUrl)
        );
    }

    getByCategoryTitle(categoryTitle: string) {
        return firstValueFrom(this.httpClient.get<Category[]>(`${this.baseUrl}/${categoryTitle}`));
    }

}
  • 项目:
export class ItemsService {

    private baseUrl = `${environment.apiUrl}/items`;

    constructor(private httpClient: HttpClient) { }

    async getAll() {
        return firstValueFrom(
            this.httpClient.get<Item[]>(this.baseUrl)
        );
    }

}

接口:

  • 类别:
export interface Item {
    id: number;
    organization: string;
    title: string;
    stDate: string;
    endDate: string;
    description: string;
    categoryTitle: string;
    categoryId: number;
}

  • 项目:
export interface Category {
    categoryId: number;
    categoryTitle: string;
}

组件

  • 卡片项目(TS):
export class CardItemComponent {

  @Input() item: Item | null = null;

  itemsService = inject(ItemsService);

}
  • 卡片项目 (HTML):
@if (item) {
<div class="item">
    <p class="title" id="org">Organization: <span>{{item.organization}}</span></p>
    <p class="title" id="title">Project: <span>{{item.title}}</span></p>
    <p class="title" id="st-date">Start date: <span>{{item.stDate}}</span></p>
    <p class="title" id="end-date">End date: <span>{{item.endDate}}</span></p>
    <p class="title" id="description">Description: <span>{{item.description}}</span>
    </p>
    <hr>
</div>
}
  • 列表项(TS):
export class ListItemsComponent {
  router = inject(Router);

  //----------- DATA-----------//
  categories: Category[] = [];
  allCategories: Item[] = [];
  itemsByCategory: { [categoryTitle: string]: Item[] } = {};
  arrItems: Item[] = [];
  category: Item | null = null;
  item: Item | null = null;


  //----------- SERVICES-----------//
  categoriesService = inject(CategoriesService);
  itemsService = inject(ItemsService);
  Object: any;


  //----------- NG-ON-INIT -----------//
  async ngOnInit() {

    // ALL CATEGORIES
    this.allCategories = await this.itemsService.getAll();

    // ALL ITEMS
    this.arrItems = await this.itemsService.getAll();

    // CATEGORIES WITH ITEMS
    this.arrItems.forEach(item => {
      const categoryTitle = item.categoryTitle;
      if (!this.itemsByCategory[categoryTitle]) {
        this.itemsByCategory[categoryTitle] = [];
      }
      this.itemsByCategory[categoryTitle].push(item);
    });
  }
}
  • 列表项(HTML):
<section>
    <div>
        @for (item of arrItems; track $index) {
        <h2>{{ item.categoryTitle }}</h2>

        <div>
            @for (item of arrItems; track $index) {
            <div>
                <card-item [item]="item"></card-item>
            </div>
            }
        </div>
        }
    </div>
</section>

我可以使用控制台在需要时查看项目列表中的对象,这意味着类别标题每个类别显示一次,并且类别中的所有项目(及其功能)都显示在类别下方标题:

Object { Projects: (5) […], Experience: (3) […], Education: (3) […], Certifications: (2) […] }
​
Certifications: Array [ {…}, {…} ]
​​
0: Object { _id: "66339fa38eaadfa13595bc5b", categoryId: 4, categoryTitle: "Certifications", … }
​​
1: Object { _id: "66339fa38eaadfa13595bc5c", categoryId: 4, categoryTitle: "Certifications", … }
​​
length: 2
​​
<prototype>: Array []
​
Education: Array(3) [ {…}, {…}, {…} ]
​
Experience: Array(3) [ {…}, {…}, {…} ]
​
Projects: Array(5) [ {…}, {…}, {…}, … ]

使用当前的 HTML @发生的情况是,我看到类别标题(和项目)的次数与项目的数量一样多。我需要显示一次类别标题,并且类别中的每个项目只显示一次,而不是像现在一样重复多次。

例如:

认证:

  • AWS....
  • 谷歌云...
  • 甲骨文...

谢谢大家!

html angular for-loop
1个回答
0
投票

最好使用普通的可观察量而不是承诺来保持代码简单,请在下面的代码中注意,我如何将所有代码移动到订阅中,原因是因为订阅下面的代码不会等待订阅完成,所以我们需要将代码移动到订阅中!

在服务中,我刚刚将 API 调用转换为简单的 http get 请求,该请求返回一个可观察值!

getAll() {
    return this.httpClient.get<Item[]>(this.baseUrl);
}

在组件中,我们订阅

getAll()
并在订阅块内设置所需的属性!

...
ngOnInit() {
    // ALL ITEMS
    this.itemsService.getAll().subscribe((res: Item[]) => {
      this.arrItems = res;
      this.allCategories = res;


    // CATEGORIES WITH ITEMS
    this.arrItems.forEach(item => {
      const categoryTitle = item.categoryTitle;
      if (!this.itemsByCategory[categoryTitle]) {
        this.itemsByCategory[categoryTitle] = [];
      }
      this.itemsByCategory[categoryTitle].push(item);
    });
    ...

分叉 Github 存储库

© www.soinside.com 2019 - 2024. All rights reserved.