【问题标题】:Single html template for multiple components in AngularAngular中多个组件的单个html模板
【发布时间】:2019-07-06 11:39:48
【问题描述】:

Angular 应用中有多个页面,它们基本相同,但几乎没有细微差别。假设他们都有一个表格,if 顶部有几个不同的按钮(具有与它们相关的特定功能)等等。

我解决这个问题的直觉是拥有一个包含所有常见功能的组件,提取组件外部的差异并使用内容投影将其注入到视图中。

今天我看到以下解决方案,只是感觉不对,并且由于某种原因让我有点紧张:

一个抽象的 PageComponent 类,没有组件装饰器,只是其中的常用功能,带有 page-component.html,在 n 其他组件中用作 templateUrl扩展了 PageComponent 类。

这与我所做的基本相同,除了一个 html 文件在多个组件中用作 templateUrl 之外。

由于“这感觉不对”并不是我可以反对的真正论据,我的问题是,你有没有见过在角度应用程序中使用这种方法。您是否知道随之而来的任何缺点/后果。

【问题讨论】:

    标签: angular


    【解决方案1】:

    我也有同样的想法,我会告诉你我为表格做了什么,然后在此基础上构建你的解决方案。

    首先让我们收集我们需要的关于mat-table的信息;

    • 作为数据的对象列表
    • 要显示的列列表

    让我们从数据开始:

    我将声明一个名为dataSource 的变量以将其用于表,而不是传递matTableDataSource,并声明一个名为list 的带有setter 函数的输入以将用户列表分配给dataSource

    dataSource = new MatTableDataSource();
    @Input() 
    set list(value: Object[]) {
        if(!value) return;
        this.dataSource = new MatTableDataSource(value);
        // here you can reassign matSort and matPaginator of the dataSource 
    }
    

    对于列(在我的情况下),我总是需要一个索引列来编号,其中包含行按钮的选项列;所以我只会传递其他列:

    我将为该表声明一个名为 displayedColumns 的变量,另一个名为 userColumns 的变量用于使用它创建一个 ngFor 和一个名为 columns 的输入:

    displayedColumns: string[] = [];
    userColumns: string[] = [];
    @Input()
    set columns(value: string[]) {
        if(!value) return;
        this.userColumns = value;
        // assign index as first column and options as last one
        this.displayedColumns.push('index', ...value, 'options');
    }
    

    顺便说一句;我假设每一列代表数据元素中的一个属性,例如:如果我传递了一个名为name 的列,那么该列的值将是element.name;但是你可以通过传递一个对象列表来使它更好:

    {
        colHeader: 'EmployeeName',
        colValue: 'name'
    }
    

    在你使用的列设置器中:

    let headers = value.map(col => col.colHeader);
    this.displayedColumns.push('index', ...headers, 'options');
    

    行按钮呢?我们怎样才能让它充满活力?

    您可以为此目的使用ng-container;所以你会期望父组件传递一个模板,你会将行作为变量传递,例如:

    <table mat-table [dataSource]="dataSource">
      <ng-container matColumnDef="index">
        <th mat-header-cell *matHeaderCellDef> No. </th>
        <td mat-cell *matCellDef="let element; let index = index"> {{index + 1}} </td>
      </ng-container>
      <ng-container *ngFor="let column of userColumns" [matColumnDef]="column">
        <th mat-header-cell *matHeaderCellDef> {{column}} </th>
        <td mat-cell *matCellDef="let element"> {{element[column]}} </td>
      </ng-container>
      <ng-container matColumnDef="options">
        <th mat-header-cell *matHeaderCellDef> </th>
        <td mat-cell *matCellDef="let element; let index = index">
          <ng-container *ngTemplateOutlet="rowBtns;context: element;">
          </ng-container>
        </td>
      </ng-container>
      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>
    

    然后传递父组件中的按钮,如:

    <reusable-table-selector>
        <ng-template #rowBtns let-element>
        <button mat-icon-button>
            <mat-icon>
                edit
            </mat-icon>
        </button>
        </ng-template>
    </reusable-table-selector>
    

    我希望您在上面的链接中阅读有关 ngContainer 的信息以避免错误。

    您可以通过这种方式进行增强,但我只是给您一个总体思路。

    我尽力提供帮助,祝你有美好的一天。

    【讨论】:

      猜你喜欢
      • 2019-12-27
      • 2021-09-30
      • 1970-01-01
      • 2017-11-06
      • 1970-01-01
      • 2017-09-23
      • 2017-09-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多