【问题标题】:Angular 6 material data table with radio buttons带有单选按钮的 Angular 6 材料数据表
【发布时间】:2019-04-12 08:02:24
【问题描述】:

我有一个 Angular 6 材料数据表,在该表的每一行中,我都有一组单选按钮。当为特定行选择单选按钮时,将触发一个事件以进行 API 调用。到目前为止一切正常。但是,如果数据表有多个页面并且我导航到第二页,然后返回到第一页,则显示为选中的单选按钮是第一次加载页面时最初选中的单选按钮;不是更新的选择。当我刷新页面时,数据重新加载,并选择了正确的单选按钮(API 调用成功更新了数据库)。不确定这是否有意义。下面是表格中一行的示例:

页面首次加载时,在这组单选按钮中选择了中间选项。如果我要选择 Beginner 选项,则按预期选择 Beginner 的单选按钮,并通过 API 调用成功地将值保存到数据库中。当我导航到第二页,然后返回第一页时,选择的单选按钮用于中级,而不是初学者。当我转到第 2 页时,状态似乎正在丢失。

我从单选按钮中删除了 (change) 和 [checked] 属性,看看会发生什么。那时,页面首次加载时没有选择任何选项。当我做出选择,导航到第 2 页,然后返回到第 1 页时,单选按钮又回到了原来的状态(没有一个被选中)。我还将单选按钮更改为原生 HTML 单选按钮,我看到了相同的行为。我在控制台中没有看到任何错误。

这是我的组件 html

<div class="mat-elevation-z8">
  <table id="dataTable" mat-table [dataSource]="dataSource">
    <ng-container matColumnDef="name">
      <th class="headerCell" mat-header-cell *matHeaderCellDef>Technology</th>
      <td style="width: 375px;" mat-cell *matCellDef="let data">{{data.name}}</td>
      <td mat-footer-cell *matFooterCellDef>&nbsp;</td>
    </ng-container>

    <ng-container matColumnDef="none">
        <th class="headerCell" mat-header-cell *matHeaderCellDef>None</th>
        <td class="radioButtonCell" mat-cell *matCellDef="let data">
          <mat-radio-button [name]="data.id" value="1" [checked]="data.level == 0 || data.level == 1 || evaluations.length == 0" (change)="saveDataLevel($event, data.dataDescription.dataGroupId)"></mat-radio-button>
        </td>
        <td mat-footer-cell *matFooterCellDef>&nbsp;</td>
    </ng-container>

    <ng-container matColumnDef="beginner">
        <th class="headerCell" mat-header-cell *matHeaderCellDef>Beginner</th>
        <td class="radioButtonCell" mat-cell *matCellDef="let data">
          <mat-radio-button [name]="data.id" value="2" [checked]="data.level == 2" (change)="saveDataLevel($event, data.dataDescription.dataGroupId)"></mat-radio-button>
          <div class="infoSubscript"><img class="icon" src="/src/assets/open-iconic/svg/info.svg" alt="Information" (click)="openDialog(data.name, data.dataDescription.dataGroupId, 2)" /></div>
        </td>
        <td mat-footer-cell *matFooterCellDef>&nbsp;</td>
    </ng-container>

    <ng-container matColumnDef="intermediate">
        <th class="headerCell" mat-header-cell *matHeaderCellDef>Intermediate</th>
        <td class="radioButtonCell" mat-cell *matCellDef="let data">
          <mat-radio-button [name]="data.id" value="3" [checked]="data.level == 3" (change)="saveDataLevel($event, data.dataDescription.dataGroupId)"></mat-radio-button>
          <div class="infoSubscript"><img class="icon" src="/src/assets/open-iconic/svg/info.svg" alt="Information" (click)="openDialog(data.name, data.dataDescription.dataGroupId, 3)" /></div>
        </td>
        <td mat-footer-cell *matFooterCellDef>&nbsp;</td>
    </ng-container>

    <ng-container matColumnDef="expert">
        <th class="headerCell" mat-header-cell *matHeaderCellDef>Advanced</th>
        <td class="radioButtonCell" mat-cell *matCellDef="let data">
            <mat-radio-button [name]="data.id" value="4" [checked]="data.level == 4" (change)="saveDataLevel($event, data.dataDescription.dataGroupId)"></mat-radio-button>
            <div class="infoSubscript"><img class="icon" src="/src/assets/open-iconic/svg/info.svg" alt="Information" (click)="openDialog(data.name, data.dataDescription.dataGroupId, 4)" /></div>
        </td>
        <td mat-footer-cell *matFooterCellDef>&nbsp;</td>
    </ng-container>

    <ng-container matColumnDef="description">
        <th class="headerCell" mat-header-cell *matHeaderCellDef>Description</th>
        <td mat-cell *matCellDef="let data">{{data.dataDescription.description}}</td>
        <td mat-footer-cell *matFooterCellDef>&nbsp;</td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    <tr mat-footer-row *matFooterRowDef="displayedColumns"></tr>
  </table>

  <mat-paginator [pageSizeOptions]="[10, 20, 30]" showFirstLastButtons></mat-paginator>
</div>

这是我的组件 ts 文件

export class TestComponent implements OnInit {
    displayedColumns: string[] = ['name', 'none', 'beginner', 'intermediate', 'advanced', 'description'];
    dataSource: MatTableDataSource<IData>;
    assessments: IAssessment[];
    dataGroupId: string = "";
    dataGroupName: string = "";

    @ViewChild(MatPaginator) paginator: MatPaginator;

    constructor(private dataService: Data, private route: ActivatedRoute, private snackBar: MatSnackBar, private dialog: MatDialog) { }

    ngOnInit() {
      this.route.queryParams.subscribe(params => {
        this.dataGroupId = params["data"];
        this.dataGroupName = params["group"];

        if (this.dataGroupId && this.dataGroupName) {
          this.getDataForGroup();
        }
      });
    }

    getDataForGroup() {
      this.dataSource = null;
      this.dataService.getDataForGroup(this.dataGroupId)
      .subscribe(s => {
        this.assessments = s.assessments;
        this.dataSource = new MatTableDataSource<IData>(s.data);
        this.paginator.firstPage();
        this.dataSource.paginator = this.paginator;
      });
    }

    saveDataLevel(event, dgrId) {
      var dataId = event.source.name;
      var level = event.source.value;
      this.dataService.saveDataLevel(dataId, level, dgrId)
        .subscribe(data => {
          let message = data ? "Data level successfully saved." : "Failed to save data level. Please try again.";
          this.snackBar.open(message, '', {
            duration: 2000,
            horizontalPosition: 'right',
            verticalPosition: 'top'
          });
        });
    }

    openDialog(dataName, dgrId, levelId) {
      this.dataService.getDataDescription(dgrId, levelId)
        .subscribe(rd => {
          this.dialog.open(LevelDescDialog, {
            width: '600px',
            data: { 
              name: dataName,
              levelDescription: rd 
            }
          });
      });
    }
  }

编辑:这是一个具有类似设置的 StackBlitz URL:https://stackblitz.com/edit/angular-s2akjp。行为一致。

【问题讨论】:

  • 你在 StackBlitz 上有这个吗?
  • @SiddAjmera 我已编辑帖子以包含 StackBlitz URL。

标签: angular angular-material


【解决方案1】:

问题已经回答了。

我的答案是单数用法:为了可以只选择一个单选按钮,请删除单选按钮组标签并单独使用,如下所示:

<mat-radio-button [value]="row"></mat-radio-button>

【讨论】:

    【解决方案2】:

    您需要在数组中设置值,将评估和事件传递给方法并设置值。

    (change)="setValue(assessment, $event.value)" 添加到每个 mat-radio-buttons

    <mat-radio-button (change)="setValue(assessment, $event.value)" [name]="assessment.id" value="1" [checked]="assessment.level == 1"></mat-radio-button>
    

    将此方法添加到组件中

    setValue(assessment,assessmentLevel){
        assessment.level = assessmentLevel
      }
    

    【讨论】:

    • 就是这样。我给了@SiddAjmera 的答案,因为他在你之前几分钟就回答了。谢谢!
    • 没问题,通常我不会在他击败我的时候发布我的答案,但我确实想表明在不先找到索引的情况下设置值是可能的。感谢您的支持。
    【解决方案3】:

    这是因为您没有将 RadioButton 上的更改保存到列表中。

    要保存更改,请将(change)="setAssessmentLevel(assessment, 1)" 添加到每个单选按钮。

    然后将setAssessmentLevel(assessment, level) 方法添加到您的组件类中,该方法会将level 值保存到您的列表中:

    setAssessmentLevel(assessment, value) {
      this.assessments[this.assessments.indexOf(assessment)] = {
        ...assessment,
        level: value
      };
    }
    

    这里有一个Sample StackBlitz 供您参考。

    【讨论】:

    • 就是这样。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    相关资源
    最近更新 更多