具有分组列的PrimeNG表无法排序

时间:2018-10-26 18:29:37

标签: angular html-table primeng

PrimeNG表可以按列排序。 https://www.primefaces.org/primeng/#/table/sort

它们也可以具有列组。 https://www.primefaces.org/primeng/#/table/colgroup

不幸的是,我很难让这两个功能一起工作。前者的示例代码简化了动态列生成的创建过程,但后者的示例代码要求手动对每个列进行编码。

我有一种编写代码的方式,在我看来它应该可以工作,并且可以正确构建和显示代码;但是单击排序图标时,它不会对数据进行排序。

这是我的代码(用于标识变量名):

<div *ngIf="(sourceObservableReturningAnArray$ | async) as arrayOfDataNeeded">
  <p-table
    [value]="arrayOfDataNeeded"
    autoLayout="true"
    sortField="firstSortedProperty"
    [rows]="25">
    <ng-template pTemplate="header" let-columns>
      <tr>
        <th rowspan="2" [pSortableColumn]="arrayOfDataNeeded.firstSortedProperty">
          Header for First Property
          <p-sortIcon [field]="arrayOfDataNeeded.firstSortedProperty"></p-sortIcon>
        </th>
        <th rowspan="2" [pSortableColumn]="arrayOfDataNeeded.secondSortedProperty">
          Header for Second Property
          <p-sortIcon [field]="arrayOfDataNeeded.secondSortedProperty"></p-sortIcon>
        </th>
        <th rowspan="2" [pSortableColumn]="arrayOfDataNeeded.thirdSortedProperty">
            Header for Third Property
            <p-sortIcon [field]="arrayOfDataNeeded.thirdSortedProperty"></p-sortIcon>
        </th>
        <th rowspan="2" [pSortableColumn]="arrayOfDataNeeded.fourthSortedProperty">
            Header for Fourth Property
            <p-sortIcon [field]="arrayOfDataNeeded.fourthSortedProperty"></p-sortIcon>
        </th>
        <th rowspan="2" [pSortableColumn]="arrayOfDataNeeded.fifthSortedProperty">
            Header for Fifth Property
            <p-sortIcon [field]="arrayOfDataNeeded.fifthSortedProperty"></p-sortIcon>
        </th>
        <th [pSortableColumn]="arrayOfDataNeeded.sixthSortedProperty" colspan="2">
            Header with Subheadings
            <p-sortIcon [field]="arrayOfDataNeeded.sixthSortedProperty"></p-sortIcon>
        </th>
        <th rowspan="2" [pSortableColumn]="arrayOfDataNeeded.seventhSortedProperty">
            Header for Seventh Property
            <p-sortIcon [field]="arrayOfDataNeeded.seventhSortedProperty"></p-sortIcon>
        </th>
      </tr>
      <tr>
        <th>Subheading 1</th>
        <th>Subheading 2</th>
      </tr>
    </ng-template>
    <ng-template pTemplate="body" let-data>
        <tr>
            <td>{{data.firstSortedProperty | currency}}</td>
            <td>{{data.secondSortedProperty}}</td>
            <td>{{data.thirdSortedProperty | date : 'shortTime'}}<br>{{data.thirdProperty | date : 'MM/dd/yyyy'}}</td>
            <td>{{data.fourthSortedProperty}}%</td>
            <td>{{data.fifthSortedProperty}}%</td>
            <td>{{data.sixthSortedProperty}}%</td>
            <td>{{data.additionalUnsortedProperty | currency}}</td>
            <td>{{data.seventhSortedProperty}}</td>
        </tr>
    </ng-template>
  </p-table>
</div>

我猜测问题出在排序字段的规范中:由于arrayOfDataNeeded是对象数组,但是具有要对其进行排序的属性的对象,也许我没有识别出对象的正确地使用相关财产。我对PrimeNG不够熟悉,不知道该怎么做。我可能可以通过对隐式上下文执行某些操作来修复它,但是我不确定该怎么做。

开始标记中的sortField =“ firstSortedProperty”可以完全按预期工作,因此数据源似乎没有问题。

如果看到我的错误,请指出!我很高兴回答澄清的问题,如果我对问题的描述不满意。我也乐于接受有关实现所需功能的替代方法的建议。

1 个答案:

答案 0 :(得分:0)

因此,对于我的原始问题,至少有两个解决方案。第一个很快速,但是有代码味。第二个问题涉及更多,但也可能是解决我提出的问题的正确方法。


第一解决方案

1)首先,将以下内容添加到component.ts文件中:

cols: any[];

this.cols = [
      { field: 'firstSortedProperty', header: 'Header for First Property'},
      { field: 'secondSortedProperty', header: 'Header for Second Property'},
      { field: 'thirdSortedProperty', header: 'Header for Third Property'},
      { field: 'fourthSortedProperty', header: 'Header for Fourth Property'},
      { field: 'fifthSortedProperty', header: 'Header for Fifth Property'},
      { field: 'sixthSortedProperty', header: 'Header for Sixth Property'},
      { field: 'additionalUnsortedProperty', header: '[It Doesn't Show, So Whatever]'},
      { field: 'seventhSortedProperty', header: 'Header for Seventh Property'},
    ];

2)然后,在component.html文件中,将[columns] =“ cols”添加到p表属性中。

<p-table
    [value]="arrayOfDataNeeded"
    [columns]="cols"
    autoLayout="true"
    sortField="firstSortedProperty"
    [rows]="25">

说明:通过为p表提供column属性的值,可以访问在每一列中找到的字段名称。 假定的columns属性包含一个将从中动态生成列的数组,但是您没有这样做。 (Tricksy!)目前,它可以正常工作,尽管目前尚无法确定将来对PrimeNG的更改是否会破坏该解决方法。


第二个解决方案

实际上可以动态生成列,同时使用标题和子标题。

1)为了实现这一点,我们必须向cols数组中的对象添加更多属性。

this.cols = [
      { field: 'firstSortedProperty', header: 'Header for First Property', hasSubs: false, isSub: false},
      { field: 'secondSortedProperty', header: 'Header for Second Property', hasSubs: false, isSub: false},
      { field: 'thirdSortedProperty', header: 'Header for Third Property', hasSubs: false, isSub: false},
      { field: 'fourthSortedProperty', header: 'Header for Fourth Property', hasSubs: false, isSub: false},
      { field: 'fifthSortedProperty', header: 'Header for Fifth Property', hasSubs: false, isSub: false},
      { field: 'sixthSortedProperty', header: 'Header for Sixth Property', hasSubs: true, isSub: false},
      { field: 'additionalUnsortedProperty', header: '[It Doesn't Show, So Whatever]', hasSubs: false, isSub: true},
      { field: 'seventhSortedProperty', header: 'Header for Seventh Property', hasSubs: false, isSub: false},
    ];

请注意,has第六的hasSubs属性为true。此属性指示标题具有子标题,并将在html文件中用于更改。

的创建。

可以从数组中省略extraUnsortedProperty对象,但我在此处包括该对象,以指示您如何动态生成子标题。我正在提供的解决方案仍然静态地指定了子标题,因为我试图着重于解决方案的基本要素。剩下的一点留给读者练习。 (我很懒?)

2)接下来,我们需要更改component.html文件中生成列的方式。我们将使用* ngIf为没有副标题的列提供一种格式设置,为有副标题的列提供另一种格式设置。

<ng-template pTemplate="header" let-columns>
  <tr [hidden]="loadOffersTable.isEmpty()">
    <th></th>
    <ng-container *ngFor="let col of columns">
      <ng-container *ngIf="col.hasSubs; else noSubs">
        <th colspan="2" [pSortableColumn]="col.field">
          {{col.header}}
          <p-sortIcon [field]="col.field" ariaLabel="Activate to sort" ariaLabelDesc="Activate to sort in descending order" ariaLabelAsc="Activate to sort in ascending order"></p-sortIcon>
        </th>
      </ng-container>
      <ng-template #noSubs>
        <th *ngIf="!col.isSub" rowspan="2" [pSortableColumn]="col.field">
          {{col.header}}
          <p-sortIcon [field]="col.field"></p-sortIcon>
        </th>
      </ng-template>
    </ng-container>
  </tr>
  <tr>
    <th></th>
    <th>Subheading 1</th>
    <th>Subheading 2</th>
  </tr>
</ng-template>

两列之间的格式差异主要取决于我们在其中任一列上设置的colspan和rowspan属性。如果它具有子标题,则设置colspan =“ 2”,以便该标题跨越两个子列。如果没有子标题,则设置rowspan =“ 2”,以便该标题也填充子标题行(对于该列)。 (不幸的是,您不能通过同时使用rowpan和colspan来尝试任何超豪华的东西。它必须是一个或另一个。)

还请注意使用逻辑容器以便在条件设置之外处理* ngFor。您需要* ngFor才能遍历各列,但是如果* ngFor位于标记内(如在通常为动态列生成而给出的示例中),则不能有条件地设置表头。 / p>

3)子标题代码实际上将保持不变。如果您要整理代码以使子标题也可以动态生成,则可以进行必要的更改。

现在,所有内容都是动态生成的,它为诸如此类的内容打开了选项:

  • 对列进行重新排序(尽管带有子标题的列不易重新排序)
  • 允许用户从表格中选择要包括/排除的列
  • 调整列的大小
  • 评论此答案
  • 允许用户在表上添加具有CRUD功能的自己的列

奖励!

您可能仍然认为您需要静态列,因为表设计需要对不同列中的数据进行不同格式或管道传输。 (如果您这么认为的话,您很可能只是个新手,但是我们都是以这种方式开始的。)幸运的是,您已经设置了一些问题,可以使用cols数组解决该问题。将[ngSwitch]与field属性一起使用,以标识单元格中正在显示哪个列的数据,并相应地设置单元格的格式。您仍然需要遍历各列,但是* ngFor可以出现在标记中了。现在,逻辑容器将出现在单元格内部中,并确定如何显示单元格的内容。这是您要做的事情的开始:

<ng-template pTemplate="body" let-nameForDataObject let-columns="columns">
  <tr>
    <td *ngFor="let col of columns">
      <ng-container [ngSwitch]="col.field">
        <ng-container *ngSwitchCase="'firstSortedProperty'">{{nameForDataObject.firstSortedProperty}}</ng-container>
        <ng-container *ngSwitchCase="'secondSortedProperty'">{{nameForDataObject.secondSortedProperty}}</ng-container>

...等等。 (使用switch语句格式化表数据不是一个聪明的技巧,也不是一个新的技巧,但是对于PrimeNG的新手来说,如何使其工作可能并不明显。)


我希望这些解决方案可以帮助您快速正确地设置PrimeNG表。祝好运!