programing

각도 재료 2 중첩된 객체를 사용한 데이터 테이블 정렬

kakaobank 2023. 5. 2. 22:53
반응형

각도 재료 2 중첩된 객체를 사용한 데이터 테이블 정렬

나는 정렬 헤더가 있는 일반적인 Angular Material 2 DataTable을 가지고 있습니다.모든 종류의 헤더는 정상적으로 작동합니다.개체를 값으로 사용하는 것은 제외합니다.이것들은 전혀 분류되지 않습니다.

예:

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

주의하세요.element.project.name

displayColumn 구성은 다음과 같습니다.

 displayedColumns = ['project.name', 'position', 'name', 'test', 'symbol'];

변화하는'project.name'로.'project'작동하지도 않습니다."project['name']"

제가 무엇을 빠뜨리고 있나요?이게 가능할까요?

Stackblitz:각도 재료2 데이터 테이블 객체 정렬

편집: 답변해 주셔서 감사합니다.동적 데이터로 이미 작동하고 있습니다.따라서 새로 중첩된 모든 속성에 대해 스위치 문을 추가할 필요가 없습니다.

다음은 제 솔루션입니다. (MatTableDataSource를 확장하는 새 DataSource를 생성할 필요가 없습니다.)

export class NestedObjectsDataSource extends MatTableDataSource<MyObjectType> {

  sortingDataAccessor: ((data: WorkingHours, sortHeaderId: string) => string | number) =
    (data: WorkingHours, sortHeaderId: string): string | number => {
      let value = null;
      if (sortHeaderId.indexOf('.') !== -1) {
        const ids = sortHeaderId.split('.');
        value = data[ids[0]][ids[1]];
      } else {
        value = data[sortHeaderId];
      }
      return _isNumberValue(value) ? Number(value) : value;
    }

  constructor() {
    super();
  }
}

이에 대한 설명서를 찾기 어려웠지만, 사용하면 가능합니다.sortingDataAccessor그리고 스위치 문.예:

@ViewChild(MatSort) sort: MatSort;

ngOnInit() {
  this.dataSource = new MatTableDataSource(yourData);
  this.dataSource.sortingDataAccessor = (item, property) => {
    switch(property) {
      case 'project.name': return item.project.name;
      default: return item[property];
    }
  };
  this.dataSource.sort = sort;
}

구성 요소에 함수를 작성하여 개체로부터 깊은 속성을 얻을 수 있습니다.그럼 다음에 사용하세요.dataSource.sortingDataAccessor아래와 같이

getProperty = (obj, path) => (
  path.split('.').reduce((o, p) => o && o[p], obj)
)

ngOnInit() {
  this.dataSource = new MatTableDataSource(yourData);
  this.dataSource.sortingDataAccessor = (obj, property) => this.getProperty(obj, property);
  this.dataSource.sort = sort;
}

columnDefs = [
  {name: 'project.name', title: 'Project Name'},
  {name: 'position', title: 'Position'},
  {name: 'name', title: 'Name'},
  {name: 'test', title: 'Test'},
  {name: 'symbol', title: 'Symbol'}
];

그리고 html로

<ng-container *ngFor="let col of columnDefs" [matColumnDef]="col.name">
      <mat-header-cell *matHeaderCellDef>{{ col.title }}</mat-header-cell>
      <mat-cell *matCellDef="let row">
        {{ getProperty(row, col.name) }}
      </mat-cell>
  </ng-container>

필드에 도트 표기법을 사용하는 한, 주어진 답은 단축할 수도 있고 전환할 필요도 없습니다.

ngOnInit() {
  this.dataSource = new MatTableDataSource(yourData);

  this.dataSource.sortingDataAccessor = (item, property) => {
     if (property.includes('.')) return property.split('.').reduce((o,i)=>o[i], item)
     return item[property];
  };

  this.dataSource.sort = sort;
}

나는 당신이 dot.separated를 사용할 수 있는 일반적인 방법을 사용합니다.와의 길.mat-sort-header또는matColumnDef경로에 의해 지시된 속성을 찾을 수 없는 경우 정의되지 않은 속성을 자동으로 반환하지 않습니다.

function pathDataAccessor(item: any, path: string): any {
  return path.split('.')
    .reduce((accumulator: any, key: string) => {
      return accumulator ? accumulator[key] : undefined;
    }, item);
}

데이터 액세스를 설정하기만 하면 됩니다.

this.dataSource.sortingDataAccessor = pathDataAccessor;

저는 @Hieu_Nguyen 솔루션을 좋아합니다.프로젝트에서 저처럼 lodash를 사용하면 솔루션이 다음과 같이 해석됩니다.

import * as _ from 'lodash';

this.dataSource.sortingDataAccessor = _.get; 

심층적인 자산 액세스를 재창조할 필요가 없습니다.

데이터 소스에 추가하기만 하면 중첩된 개체에 액세스할 수 있습니다.

this.dataSource.sortingDataAccessor = (item, property) => {
    // Split '.' to allow accessing property of nested object
    if (property.includes('.')) {
        const accessor = property.split('.');
        let value: any = item;
        accessor.forEach((a) => {
            value = value[a];
        });
        return value;
    }
    // Access as normal
    return item[property];
};

여러 중첩된 개체 수준에 맞게 사용자 지정했습니다.

this.dataSource.sortingDataAccessor =
  (data: any, sortHeaderId: string): string | number => {
    let value = null;
    if (sortHeaderId.includes('.')) {
      const ids = sortHeaderId.split('.');
      value = data;
      ids.forEach(function (x) {
        value = value? value[x]: null;
      });
    } else {
      value = data[sortHeaderId];
    }
    return _isNumberValue(value) ? Number(value) : value;
  };

또 다른 대안은, 아무도 여기에 버리지 않은, 먼저 기둥을 평평하게 만드는 것입니다.

yourData.map((d) => 
   d.flattenedName = d.project && d.project.name ? 
                     d.project.name : 
                     'Not Specified');

this.dataSource = new MatTableDataSource(yourData);

각각의 장단점을 가진 또 다른 대안일 뿐입니다!

중첩 객체 정렬과 같이 일부 확장 기능이 있는 Angular 재료 테이블을 사용하려면 https://github.com/mikelgo/ngx-mat-table-extensions/blob/master/libs/ngx-mat-table/README.md 을 참조하십시오.

이 lib를 만든 이유는 매트 테이블의 일부 기능이 상자 밖에 없기 때문입니다.

고급 정렬은 @Hieu Nguyen이 제안한 답변과 비슷하지만 대문자와 소문자로 적절하게 정렬되도록 약간 확장되었습니다.

요소별로 정렬하려고 합니다['project.name '].분명히 원소는 그러한 속성을 가지고 있지 않습니다.

MatTableData 소스를 확장하고 중첩된 개체 속성별 정렬을 지원하는 사용자 지정 데이터 소스를 쉽게 만들 수 있어야 합니다.사용자 지정 소스 사용에 대한 material.angular.io 문서의 예제를 확인하십시오.

저도 같은 문제가 있었습니다. 처음에 몇 가지 오류가 발생한 제안을 테스트함으로써 "스위치(속성)"를 추가하여 해결할 수 있었습니다.

this.dataSource.sortingDataAccessor =(item, property) => {
    switch (property) {
    case 'project.name': return item.project.name;

    default: return item[property];
    }
  };

MatTableDataSource 사용 전체 MatSort 문제 솔루션 확인

HTML로

    <ng-container matColumnDef="createdDate" @bounceInLeft>
      <th mat-header-cell *matHeaderCellDef mat-sort-header class="date"> Created date
      </th>
          <td mat-cell *matCellDef="let element" class="date"> {{element.createdDate
           | date :'mediumDate'}} </td>
   </ng-container>

  <ng-container matColumnDef="group.name">
    <th mat-header-cell *matHeaderCellDef mat-sort-header class="type"> Group </th>
    <td mat-cell *matCellDef="let element" class="type"> {{element.group.name}} </td>
  </ng-container>

@ViewChild(MatSort, { static: true }) sort: MatSort;

    ngOnInit() {
      this.dataSource = new MatTableDataSource(yourData);
      this.dataSource.sortingDataAccessor = (item, property) => {
    switch(property) {
      case 'project.name': return item.project.name;
      default: return item[property];
    }
  };
  this.dataSource.sort = sort;
}

테이블 열이 제대로 정렬되지 않아 데이터 작업을 위해 답변 중 하나를 수정했습니다.

function pathDataAccessor(item: any, path: string): any {
  return (item: any, path: string): any => {
    return path.split(".").reduce((accumulator: any, key: string) => {
      let returnValue;
      if (accumulator) {
        returnValue = accumulator[key];
      } else {
        returnValue = undefined;
      }
      if (typeof returnValue === "string") {
        returnValue = returnValue.trim().toLocaleLowerCase();
      }
      return returnValue;
    }, item);
  };
}

저는 명확한 솔루션을 찾고 모든 입력 데이터에 대해 작동합니다.

    this.dataSource.sortingDataAccessor = (obj: any, property: string) => property.split('.').reduce((o, p) => o && o[p], obj);
    this.dataSource.sort = this.sort;

HTML 파일에서 중첩된 개체를 mat-sort-header로 설정해야 합니다.EX:mat-sort-header="User.Name"

      <ng-container matColumnDef="UserName">
        <th mat-header-cell *matHeaderCellDef mat-sort-header="User.Name">User</th>
        <td mat-cell *matCellDef="let row">{{ row.User.Name}}</td>
      </ng-container>

설명:첫 번째 단계: 데이터 소스를 설정합니다.섹션: 일반 정렬 데이터 가속기를 설정합니다.셋째: 데이터 소스에 대한 정렬을 호출합니다.

  this.dataSource = new MatTableDataSource(project.ActivityLog.items);
  setTimeout(() => {
  
    this.dataSource.sortingDataAccessor = (obj: any, property: string) => property.split('.').reduce((o, p) => o && o[p], obj);
    this.dataSource.sort = this.sort;

  })
}

데이터에 아래 예제와 같은 내부 개체가 포함된 경우

myData = [ {service: 'SRS',
      team: {id: 'T1', name: 'Blasters'},
      rank: 23,
      .....
     },
     { service: 'COC',
      team: {id: 'T2', name: 'Strikers'},
      rank: 7,
      .....
     },
     ......
]

그러면 사용자 정의 정렬 기능을 사용할 수 있습니다.

<table mat-table [dataSource]="myData" #outersort="matSort" matSort>
      <ng-container matColumnDef="service">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>SERVICE</th>
        <td mat-cell *matCellDef="let element">
          {{ element.service }}
        </td>
      </ng-container>
      <ng-container matColumnDef="team.name">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>TEAM</th>
        <td mat-cell *matCellDef="let element">
          {{ element.team.name }}
        </td>
      </ng-container>
     .....

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

표시된 열은 다음과 같이 중첩된 개체를 나타내야 합니다.

displayedColumns = ['service','team.name', 'rank']

및 ts 파일

@ViewChild(MatSort) MySort: MatSort;

 .....
  this.dataSource = new MatTableDataSource(myData);
  this.dataSource.sortingDataAccessor = (item, property) => {
    return eval('item.'+property);
  };
  this.dataSource.sort = MySort;
.....

언급URL : https://stackoverflow.com/questions/48891174/angular-material-2-datatable-sorting-with-nested-objects

반응형