【问题标题】:Angular: How to delete selected data row?Angular:如何删除选定的数据行?
【发布时间】:2019-12-30 14:47:40
【问题描述】:

我正在使用<mat-radio-button> 列表。当我首先单击然后单击第二个而不是单击第一个返回时。当我单击第一个单选按钮时,它不起作用。然后当我点击删除按钮时,它会删除第一个和第二个。

我提供了下面的代码和Demo 链接供您参考。

HTML

    <div class="example-container mat-elevation-z8">
  <mat-chip class="pointer" mat-raised-button color="primary" (click)="removeSelectedRows()">
    Remove Selected Rows
  </mat-chip>
  <mat-table #table [dataSource]="dataSource">

    <!-- Checkbox Column -->
    <ng-container matColumnDef="select">
      <mat-header-cell *matHeaderCellDef>
        <!-- <mat-checkbox (change)="$event ? masterToggle() : null"
                      [checked]="selection.hasValue() && isAllSelected()"
                      [indeterminate]="selection.hasValue() && !isAllSelected()">
        </mat-checkbox> -->
      </mat-header-cell>
      <mat-cell *matCellDef="let row">
        <mat-radio-button (click)="$event.stopPropagation()"
                      (change)="$event ? selection.toggle(row) : null"
                      [checked]="selection.isSelected(row)">
        </mat-radio-button>
      </mat-cell>
    </ng-container>

    <!-- Position Column -->
    <ng-container matColumnDef="position">
      <mat-header-cell *matHeaderCellDef> No. </mat-header-cell>
      <mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
    </ng-container>

    <!-- Name Column -->
    <ng-container matColumnDef="name">
      <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
      <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
    </ng-container>

    <!-- Weight Column -->
    <ng-container matColumnDef="weight">
      <mat-header-cell *matHeaderCellDef> Weight </mat-header-cell>
      <mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
    </ng-container>

    <!-- Symbol Column -->
    <ng-container matColumnDef="symbol">
      <mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell>
      <mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
    </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;"
             (click)="selection.toggle(row)">
    </mat-row>
  </mat-table>

    <mat-paginator #paginator
                 [pageSize]="3"
                 [pageSizeOptions]="[5, 10, 20]"
                 >
  </mat-paginator>

</div>

组件

    displayedColumns = ['select', 'position', 'name', 'weight', 'symbol'];
  data = Object.assign( ELEMENT_DATA);
  dataSource = new MatTableDataSource<Element>(this.data);
  selection = new SelectionModel<Element>(true, []);


  @ViewChild(MatPaginator) paginator: MatPaginator;

  ngAfterViewInit() {
    this.dataSource.paginator = this.paginator;
  }

  constructor(){
    console.log(this.data);
  }

  /** Whether the number of selected elements matches the total number of rows. */
  isAllSelected() {
    const numSelected = this.selection.selected.length;
    const numRows = this.dataSource.data.length;
    return numSelected === numRows;
  }

  removeSelectedRows() {
    console.log(this.selection.selected)
     this.selection.selected.forEach(item => {
      let index: number = this.data.findIndex(d => d === item);
      console.log(this.data.findIndex(d => d === item));
      this.dataSource.data.splice(index,1);

      this.dataSource = new MatTableDataSource<Element>(this.dataSource.data);
    });
    this.selection = new SelectionModel<Element>(true, []);
    console.log(this.selection)
  }

  /** Selects all rows if they are not all selected; otherwise clear selection. */
  masterToggle() {
    this.isAllSelected() ?
      this.selection.clear() :
      this.dataSource.data.forEach(row => this.selection.select(row));
  }
}

感谢和问候。

【问题讨论】:

  • 试试 this.dataSource.data = this.dataSource.data.splice(index,1); / splice 返回一个值,它不会修改你的实际对象
  • 无论如何,最好不要直接对dataSource进行操作,您可以创建一个新的obj并最终将其分配给您的dataSource。:let source = this.dataSource.data;让 index = source.findIndex(d => d === item); source = source.splice(index, 1); this.dataSource.data = 源;
  • 感谢您的评论...我会尝试..
  • 您不应该改用mat-checkbox 吗?是否要限制用户同时删除多行?你到底为什么使用mat-radio-button
  • @nash11 是的..我想限制用户同时删除多行..一次只能选择一行

标签: angular typescript angular-material radio-button


【解决方案1】:

您的问题是您正在尝试使用selection.selected,它返回一个包含所有选择的行的数组,而实际上您只想从表中删除一个值。如果我们希望用户一次只能删除一行,我们只需要担心用户选择的最后一行。我们可以去掉$event.stopPropagation,这样无论用户点击单选按钮还是点击行,都会触发相同的事件。

<mat-cell *matCellDef="let element; let i = index">
    <mat-radio-button [checked]="selectedIndex === i">
    </mat-radio-button>
</mat-cell>

...

<mat-row *matRowDef="let row; let i = index; columns: displayedColumns;" (click)="selectedIndex = i">
</mat-row>

然后在你的组件中

selectedIndex: number;

removeSelectedRows() {
    let index: number = this.selectedIndex;
    this.dataSource.data = [...this.dataSource.data.slice(0, index), ...this.dataSource.data.slice(index + 1)];
    this.selectedIndex = null; // This will not be required when position is used to delete element
}

我已尝试不要对您的代码进行太多更改,并使用 slice 执行此操作,但 IMO 最好在 Element 中使用唯一值,例如 position 并使用 filter 过滤掉从dataSource.data 中选择的位置。

<mat-cell *matCellDef="let element">
    <mat-radio-button [checked]="selectedPosition === element.position">
    </mat-radio-button>
</mat-cell>

...

<mat-row *matRowDef="let row; columns: displayedColumns;" (click)="selectedPosition = row.position">
</mat-row>

在组件中

selectedPosition: number;

removeSelectedRows() {
    this.dataSource.data = this.dataSource.data.filter(element => element.position !== this.selectedPosition);
}

这是StackBlitz 上的一个工作示例。

【讨论】:

【解决方案2】:

如果您一次删除一行,则使用单选按钮毫无意义。我对您的代码进行了一些更改,并根据您的要求创建了输出,

注意:即使你想使用单选按钮这是不好的做法,这就是答案

<mat-chip class="pointer" mat-raised-button color="primary" (click)="removeSelectedRows(element)">
        Remove Selected Rows
    </mat-chip>
    <mat-table #table [dataSource]="dataSource">


        <!-- Checkbox Column -->
        <ng-container matColumnDef="select">
            <mat-header-cell *matHeaderCellDef>
            </mat-header-cell>
            <mat-cell *matCellDef="let element;let i = index; ">
                <mat-radio-button (click)="rowIndex(i)">
                </mat-radio-button>
            </mat-cell>
        </ng-container>

在您的组件中用以下代码替换您的删除功能,

index: number;
rowIndex(i){
this.index=i;
}

removeSelectedRows(element) {
      this.dataSource.data.splice(this.index,1);
      this.dataSource._updateChangeSubscription();
  }

希望这会有所帮助。不要忘记接受答案。谢谢

This is working Stackblitz project

【讨论】:

  • 非常感谢您的回答...我感觉很糟糕
  • 这是什么问题,这是完美的,易于理解,而且效果很好
  • @swapy 编辑了我的答案,这是正常工作,请您再看一遍
  • 你能给我链接 stackblitz 你制作 gif 图像吗?
  • @IndrajithEkanayake - 请不要强迫提问者接受你的答案。这是由提问者决定的。相反,证明你的答案比其他答案更好。虽然_updateChangeSubscription 可以工作,但它在幕后做了很多其他事情,你不需要做这些事情,只需简单地添加一行。因此,虽然您的答案似乎很容易理解,但请记住您正在调用一个包含代码的函数。所以你可以在 1 行代码中轻松完成的工作现在很容易变成 30 多行。
猜你喜欢
  • 1970-01-01
  • 2020-05-09
  • 2019-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-01
  • 1970-01-01
相关资源
最近更新 更多