首页 > 解决方案 > 在同一页面中多次使用相同的组件

问题描述

我开始使用 Angular 进行开发。我用数据创建了一个 API。这些数据是这样排序的

对于每个“机构”,n 个“培训”。对于每个“培训”,n 个“小组”。我通过服务请求我的 API。

因此,在我想在扩展面板中显示的页面中:https ://material.angular.io/components/expansion/overview 培训作为标题和关联的组列表。

在代码中,我有显示 n 个培训的“training-view.component”,在此培训中,我放置了 n 个“group-view.component”。

假设我有 3 次培训,我的网站将显示 3 次相同组的培训(图片更明确): http: //puu.sh/CogJM/476c792726.png

我试过这个:Angular 2:重复使用相同的组件 但是“唯一ID”不是解决方案。也许我不能在同一页面中使用相同的组件,但是当我使用“ngFor”时它可以工作

所有代码都是代码的一部分。训练视图.components.ts :

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

trainings: Training[];
trainingSubscription: Subscription;
[...]

ngOnInit() {

this.trainingSubscription = this.TrainingService.trainingsSubject.subscribe(
  (groups: any[]) => {
    this.trainings = groups;
  }
);
this.TrainingService.emitTrainingsSubject();

this.onFetch();
}

训练视图 html

<mat-accordion>
    <mat-expansion-panel *ngFor="let training of trainings">
      <mat-expansion-panel-header>
        <mat-panel-title>
          {{training.name}}
        </mat-panel-title>
        <mat-panel-description>
          Liste des groupes
        </mat-panel-description>
      </mat-expansion-panel-header>
      <app-group-view
        [idTraining]="training.id"
        [id]="id" 
      ></app-group-view>

      </mat-form-field>
    </mat-expansion-panel>
  </mat-accordion>

app-group-view 将获取所有组并将在“groups.components”上执行“ngFor”

所以组视图 ts

        import { Component, OnInit, Input } from '@angular/core';
    import { ActivatedRoute } from '@angular/router';
    import { GroupService } from '../services/group.service';
    import { Subscription } from 'rxjs';
    import { Group } from '../model/Group.model';


    let uniqueId = 0;
    @Component({
      selector: 'app-group-view',
      templateUrl: './group-view.component.html',
      styleUrls: ['./group-view.component.css']
    })
    export class GroupViewComponent implements OnInit {
      @Input() idTraining: number;
      id = "tr-" + uniqueId++;
      groups: Group[];
      groupSubscription: Subscription;
      idFormation = null;




      constructor(
        private GroupService: GroupService,
        private route: ActivatedRoute){

      }
      onSave(){
        console.log('save');
      }

      ngOnInit() {

        // this.idFormation = this.idTraining != null ? this.idTraining : this.route.snapshot.params['id'];
        this.idFormation =  this.idTraining ;

        this.groupSubscription = this.GroupService.groupsSubject.subscribe(
          (groups: any[]) => {
            this.groups = groups;

          }
        );
        this.GroupService.emitGroupsSubject();
        this.onFetch();
      }

      addGroup(){

        if(this.idFormation != null){
          let newGroup : Group= new Group(undefined,"nouveau groupe",this.idFormation,""); 
          this.groups.push(newGroup);
        }
      }

      onFetch() {
        //const id = this.route.snapshot.params['id'];
        this.GroupService.getGroupsFromServer(this.idTraining);

      }

      ngOnDestroy() {

        this.groupSubscription.unsubscribe();

      }
    }

html:

<app-groups *ngFor="let group of groups;let i = index" 
                [groupName]="group.name"
                [groupFormation]="group.training_name"
                [index]="i"
                [idGroup]="group.id"
                [id]="id" 
                >
    </app-groups>

应用组是一个简单的 html 组件。

组服务.ts

@Injectable()
export class GroupService {

  groupsSubject = new Subject<any[]>();

  constructor(private httpClient: HttpClient) { }
  groups : Group[] ;
  getGroupsFromServer(idGroups  : number = null) {
      let url = 'https://XXX.fr/';
      if(idGroups != null){
        url += '/trainings/' + idGroups +"/groups";
      }else{
        url += 'groups/';
      }
      this.httpClient
        .get<any[]>(url)
        .subscribe(
          (response) => {
            this.groups = response;
            this.emitGroupsSubject();
          },
          (error) => {
            console.log('Erreur ! : ' + error);
          }
        );
 }
 emitGroupsSubject(){
      if(this.groups != null)
        this.groupsSubject.next(this.groups.slice());
 }
}

见下图我写了我想要的。 http://puu.sh/CogJM/476c792726.png

我希望你能理解我的问题,谢谢你的帮助 Thomas

更新

我尝试了@Gérôme Grignon 的解决方案

训练 :

<mat-accordion>
    <mat-expansion-panel *ngFor="let training of trainings">
        <mat-expansion-panel-header>
            <mat-panel-title>
                {{training.name}}
            </mat-panel-title>
            <mat-panel-description>
              Liste des groupes
            </mat-panel-description>
        </mat-expansion-panel-header>
        <app-group-view
          [idTraining]="training.id"
          [id]="id" 
        ></app-group-view>


    </mat-expansion-panel>
</mat-accordion>

组视图:

 <li class="list-group-item" *ngFor="let group of groups">
          <h4>{{ group.training_name }} groupe {{ group.name }} </h4> 
        </li>

结果 :

每次培训我都有相同的小组。如果我转到网络选项卡(mozillia 控制台),它对应于最后一个 ajax 请求:http : //puu.sh/Coj8v/12a01b2f72.png Thnaks you @Gérôme Grignon

标签: angularcomponents

解决方案


通过删除主题和订阅组件来简化与服务的通信。然后迭代 groups 变量。

服务 :

getGroupsByTraining(id) {
// ...
return this.httpClient.get(url); }

组视图组件:

groups;
@Input() idTraining: number;

ngOnInit() {
this.service.getGroupsByTraining(idTraining).subscribe(data => this.groups = data); }

推荐阅读