【问题标题】:Add and remove component dynamically from mat-list in Angular 7从 Angular 7 的 mat-list 中动态添加和删除组件
【发布时间】:2019-07-10 21:49:39
【问题描述】:

在我的一个 Angular 组件中,我有一个 mat-list,我想用它来显示子组件列表。我希望用户能够通过单击列表下方的按钮将组件添加到此列表,并通过单击组件本身上的删除按钮从列表中删除组件。

就上下文而言,正在创建/删除的子组件是一个涉及保存有关 IP 地址范围的信息的组件。它包含两个输入,一个用于起始范围,一个用于结束范围。

我可以使用添加功能,但它的实现方式似乎不正确。我目前的方法是保存一个IpRange 对象数组(包含两个字符串的简单对象),然后使用*ngFor 每次将对象添加到该数组时都会生成一个新组件。该组件是通过子组件中的@Input ipRange: IpRange 生成的。

但是,当我实例化这些新组件时,我通过将一个空对象传递给数组来创建它们,这感觉不对。

父模板

<div class="row">
            <div class="col-12">
                <mat-list>
                    <app-add-ip-dialog *ngFor="let ipRange of ipRanges" [ipRange]="ipRange"></app-add-ip-dialog>
                </mat-list>
            </div>
        </div>

父组件

export class ParentComponent implements OnInit{

  ipRanges: IpRange[];

  constructor() {}

  ngOnInit() {
    this.ipRanges = [];
  }

  addIpRange(): void {
    this.ipRanges.push({startingRange: '', endingRange: ''});
    console.log(this.ipRanges);
  }
}

子组件

export class AddIpDialogComponent implements OnInit, OnChanges {

  @Input() ipRange: IpRange;

  constructor(){}

  ngOnInit() {
  }

  ngOnChanges(changes: SimpleChanges): void {
    console.log(this.ipRange.startingRange + ' : ' + this.ipRange.endingRange);
  }
}

IpRange 接口

export interface IpRange {
    startingRange: string;
    endingRange: string;
}

我希望能够在每次用户单击添加按钮时实例化一个新组件,然后每个组件都能够通过两种方式绑定来跟踪其startingRangeendingRange

然后,当用户想要删除其中一个组件时,他们只需单击组件上的删除按钮,然后将其从 mat-list 中删除。

【问题讨论】:

    标签: angular


    【解决方案1】:

    这些必须是单独的组件吗?我最近做了一些非常相似的事情,您可以在表单中列出要上传的文件,并且我在其中构建了一个添加/删除输入功能,该功能将为每个要上传的文件创建一个新输入,并在发布数据时发送它在一个数组中。那条路线可能更容易。如果您愿意做出改变,请告诉我,我可以向您展示一些代码。我使用Angular material Reactive Forms

    【讨论】:

      【解决方案2】:

      我建议使用 Service 作为集中式数据存储来将 ipRanges 数据分发到您的组件:

      @Injectable({providedIn: 'root'})
      export class IpRangesService() {
       ipRanges: ipRange[];
       ngOnInit() {
          this.ipRanges = [];
        }
      
        addIpRange() {
          this.ipRanges.push({startingRange: '', endingRange: ''});
          console.log(this.ipRanges);
        }
        removeIpRange(index) {
          this.ipRanges.slice(index,1);
        }
        getIpRangeData() {
          return this.ipRanges
        }
      }
      

      然后分发给你的父组件

      在父ts文件中:

      export class ParentComponent implements OnInit{
      
        ipRanges: IpRange[];
      
        constructor(private ipRangeService : IpRangeService) {}
      
        ngOnInit() {
          this.ipRanges = this.ipRangeService.getIpRangeData();
        }
      }
      

      在您的父 HTML 模板中,将 index 属性传递给您的子组件,它充当您子组件的标识符:

      <div class="row">
          <div class="col-12">
              <mat-list>
                  <app-add-ip-dialog 
                      *ngFor="let ipRange of ipRanges, let i = index" 
                      [ipRange]="ipRange"
                      [id]="i"> 
                  </app-add-ip-dialog>
              </mat-list>
          </div>
      </div>
      

      现在您可以使用子组件中的索引,使用上述服务提供的方法removeIpRange() 删除自身:

      export class AddIpDialogComponent implements OnInit, OnChanges {
      
        @Input() ipRange: IpRange;
        @Input() id: number;
        constructor(private ipRangeService : IpRangeService){}
      
        ngOnInit() {
        }
      
        //function that listen to the remove click event
        onRemoveButtonClicked() {
           this.ipRangeService.removeIpRange(id);
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-12-09
        • 2017-11-18
        • 1970-01-01
        • 2019-03-25
        • 1970-01-01
        • 2019-08-21
        • 2018-09-15
        • 1970-01-01
        • 2017-05-18
        相关资源
        最近更新 更多