#angular #datagrid #nested
Вопрос:
Я использую сетку данных Clarity для отображения таблицы с параметрами фильтрации и разбиения на страницы. Два моих столбца являются вложенными объектами, но фильтр для этих двух столбцов — имя воспитателя и код воспитателя-не работает; в результате получается пустой объект. Фильтр отлично работает в столбце состояния, который не является вложенным, и поэтому я использую clrDgField=»статус» без квадратных скобок. сумма также не работает — это означает, что объект пуст при вводе чисел. *Я только что понял, что проблема не во вложенных объектах; столбец имя воспитателя действительно работает, когда вы вводите полное имя. Похоже, что только фильтры по числам, такие как сумма и код, не работают. *это работает, если я изменю тип в Firestore на строку. Интересно, это единственный выход? Вот мой код: шаблон
<ng-container *ngIf="vm$ | async as transactions">
<clr-datagrid style="min-height: 16rem"
(clrDgRefresh)="onTableRefresh($event)">
<clr-dg-column>
Date Requested
</clr-dg-column>
<clr-dg-column>
<ng-container *clrDgHideableColumn="{hidden: true}">
Transaction ID
</ng-container>
</clr-dg-column>
<clr-dg-column clrDgField="amount">
Amount
</clr-dg-column>
<clr-dg-column [clrDgField]="'caregiver.name'">
<ng-container *clrDgHideableColumn="{hidden: false}">
Caregiver Name
</ng-container>
</clr-dg-column>
<clr-dg-column clrDgField="caregiver.caregiverCode">
<ng-container *clrDgHideableColumn="{hidden: false}">
Caregiver Code
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container *clrDgHideableColumn="{hidden: true}">
Bank Account ID
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container *clrDgHideableColumn="{hidden: true}">
Benefit Card ID
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container>
Benefit Card Auth. Status
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container *clrDgHideableColumn="{hidden: true}">
Caregiver ID
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container *clrDgHideableColumn="{hidden: true}">
Debit card ID
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container *clrDgHideableColumn="{hidden: true}">
Processing Fee
</ng-container>
</clr-dg-column>
<clr-dg-column clrDgField="status">
<ng-container *clrDgHideableColumn="{hidden: false}">
Status
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container>
Payback Date
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container>
Number of Weeks
</ng-container>
</clr-dg-column>
<clr-dg-row *ngFor="let transaction of transactions" [clrDgItem]="transaction">
<clr-dg-cell>{{transaction?.requestedAt?.toMillis() | date: 'medium'}}</clr-dg-cell>
<clr-dg-cell>{{transaction?.transactionId}}</clr-dg-cell>
<clr-dg-cell>{{transaction?.amount | currency}}</clr-dg-cell>
<clr-dg-cell>{{transaction?.caregiver?.name | titlecase}}</clr-dg-cell>
<clr-dg-cell>{{transaction?.caregiver?.caregiverCode}}</clr-dg-cell>
<clr-dg-cell>{{transaction?.bankAccountId}}</clr-dg-cell>
<clr-dg-cell>{{transaction?.benefitCardId}}</clr-dg-cell>
<clr-dg-cell class="center">
<div>
<span *ngIf="transaction?.benefitCardAuth?.succeeded == true">
<cds-icon shape="success-standard" status="success" solid></cds-icon></span>
<span *ngIf="transaction?.benefitCardAuth?.succeeded == false">
<cds-icon shape="error-standard" status="danger" solid></cds-icon></span>
</div>
</clr-dg-cell>
<clr-dg-cell>{{transaction?.caregiverId}}</clr-dg-cell>
<clr-dg-cell>{{transaction?.debitCardId}}</clr-dg-cell>
<clr-dg-cell>{{transaction?.processingFee | currency}}</clr-dg-cell>
<clr-dg-cell>{{transaction?.status}}</clr-dg-cell>
<clr-dg-cell>{{transaction?.paybackDate.toDate() | date: 'medium'}}</clr-dg-cell>
<clr-dg-cell class="center">{{transaction?.weekNumber}}</clr-dg-cell>
</clr-dg-row>
<clr-dg-detail *clrIfDetail="let detail">
<clr-dg-detail-body>
<ul class="clr-timeline clr-timeline-horizontal">
<li class="clr-timeline-step disabled">
<ng-container *ngTemplateOutlet="timelineStep; context:{data: { title: 'Benefit Card Authorization', success:
detail?.benefitCardAuth?.succeeded, error: detail?.benefitCardAuth amp;amp; !detail?.benefitCardAuth?.succeeded, missing: !detail?.benefitCardAuth}}"></ng-container>
</li>
<li class="clr-timeline-step disabled">
<ng-container *ngTemplateOutlet="timelineStep; context:{data: { title: 'Instant Card Payments', success:
detail?.debitCardInstantPay?.status === 'PAID', inProcess:
detail?.debitCardInstantPay amp;amp; detail.debitCardInstantPay.status === 'IN_PROCESS', error:
detail?.debitCardInstantPay amp;amp; (detail.debitCardInstantPay.status === 'ERROR' ||
detail.debitCardInstantPay.status === 'UNPAID' ||
detail.debitCardInstantPay.status === 'VOID' ||
detail.debitCardInstantPay.status === 'EXPIRED' ) , missing:
!detail?.debitCardInstantPay}}"></ng-container>
</li>
<li class="clr-timeline-step disabled">
<ng-container *ngTemplateOutlet="timelineStep; context:{data: { title: 'Benefit Card Capture', success:
detail?.benefitCardCapture?.succeeded, error: detail?.benefitCardCapture amp;amp; !detail?.benefitCardCapture?.succeeded, missing: !detail?.benefitCardCapture}}"></ng-container>
</li>
<li class="clr-timeline-step disabled">
<ng-container *ngTemplateOutlet="timelineStep; context:{data: { title: 'Payback Schedule', success:
detail?.paybackSchedule?.status === 'COMPLETED', scheduled:
detail?.paybackSchedule?.status === 'SCHEDULED', error:
detail?.paybackSchedule amp;amp; (detail.paybackSchedule.status === 'CANCELLED' ||
detail.paybackSchedule.status === 'ERROR') , missing:
!detail?.paybackSchedule}}"></ng-container>
</li>
</ul>
<clr-tabs>
<clr-tab>
<button clrTabLink>Benefit Card Authorization/Capture</button>
<clr-tab-content *clrIfActive>
<app-benefit-cards [transactionId]="detail?.transactionId"></app-benefit-cards>
</clr-tab-content>
</clr-tab>
<clr-tab>
<button clrTabLink>Instant Payments</button>
<clr-tab-content *clrIfActive>
<app-instant-payments [transactionId]="detail?.transactionId"></app-instant-payments>
</clr-tab-content>
</clr-tab>
<clr-tab>
<button clrTabLink>Payback Schedules</button>
<clr-tab-content *clrIfActive>
<app-payback-schedule> [transactionId]="detail?.transactionId"></app-payback-schedule>
</clr-tab-content>
</clr-tab>
</clr-tabs>
</clr-dg-detail-body>
</clr-dg-detail>
<clr-dg-footer>
<button (click)="previousPage()" class="btn btn btn-info btn-sm float-right">Prev</button>
<button (click)="nextPage()" class="btn btn btn-info btn-sm float-left">Next</button>
</clr-dg-footer>
</clr-datagrid>
</ng-container>
<ng-template #timelineStep let-detail=data>
<li class="clr-timeline-step disabled">
<span aria-label="succeeded" *ngIf="detail.success"><cds-icon shape="success-standard" status="success"
solid></cds-icon></span>
<span aria-label="in_process" *ngIf="detail.inProcess"><cds-icon shape="error-standard" status="warning"
solid></cds-icon></span>
<span aria-label="scheduled" *ngIf="detail.scheduled"><cds-icon shape="alarm-clock" status="success"
solid></cds-icon></span>
<span aria-label="failed" *ngIf="detail.error"><cds-icon shape="error-standard" status="danger"
solid></cds-icon></span>
<span aria-label="missing" *ngIf="detail.missing"><cds-icon shape="circle"></cds-icon></span>
<div class="clr-timeline-step-body">
<span class="clr-timeline-step-title">{{detail.title}}</span>
<span class="clr-timeline-step-description" *ngIf="detail.description">{{detail.description}}</span>
</div>
</li>
</ng-template>
компонент:
import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core';
import {catchError, distinctUntilChanged, map, switchMap, tap} from 'rxjs/operators';
import {AngularFirestore} from '@angular/fire/firestore';
import {Transaction, TransactionState} from './Transaction.interface';
import {BehaviorSubject, Observable} from 'rxjs';
// @ts-ignore
import {Paginator} from './Paginator.interface';
import {ClrDatagridStateInterface} from '@clr/angular';
let STATE: TransactionState = {
transactions: [],
pagination: {
after: undefined,
before: undefined,
limit: 10,
filters: [],
}
};
@Component({
selector: 'app-transactions',
templateUrl: './transactions.component.html',
styleUrls: ['./transactions.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TransactionsComponent implements OnInit {
@Input() caregiverId: any;
// public transactions: Transaction[];
// public transactionId;
store = new BehaviorSubject(STATE);
public state$ = this.store.asObservable();
dataGridTimeout: any;
transactions$ = this.state$.pipe(
map((state) => state.transactions),
distinctUntilChanged(),
);
pagination$ = this.state$.pipe(
map((state) => state.pagination),
distinctUntilChanged(),
);
vm$ = this.pagination$.pipe(switchMap((pagination
) => this.afs
.collection<Transaction>('transactions', (ref) => {
let query: any = ref;
if (this.caregiverId) {
query = query
.where('caregiverId', '==', this.caregiverId);
}
if (pagination.filters?.length){
for (const filter of pagination.filters) {
const property = filter.property;
const value = filter.value;
query = query.where(property, '==', value);
}
}
if (pagination.after) {
query = query
.orderBy('requestedAt', 'desc')
.orderBy('transactionId')
.startAfter(pagination.after.requestedAt, pagination.after.transactionId)
.limit(pagination.limit);
} else if (pagination.before) {
query = query
.orderBy('requestedAt', 'desc')
.orderBy('transactionId')
.endBefore(pagination.before.requestedAt, pagination.before.transactionId)
.limitToLast(pagination.limit);
} else {
query = query
.orderBy('requestedAt', 'desc')
.limit(pagination.limit);
}
return query;
})
.valueChanges().pipe(
tap(transactionsArray => {
const transactions = transactionsArray;
this.updateState({...STATE, transactions});
console.log(transactions);
}
))),
catchError(err => {
console.log(err)
return []
})
);
constructor(public afs: AngularFirestore) {
// this.vm$.subscribe(d =>{
// const transactions = d;
// this.updateState({...STATE, transactions});
// console.log(d);
// })
}
onTableRefresh(state: ClrDatagridStateInterface<Transaction>): void {
this.setDataGridState(state);
if (this.dataGridTimeout) {
clearTimeout(this.dataGridTimeout);
}
}
setDataGridState(tableState: ClrDatagridStateInterface): void {
const dataState = this.store.getValue();
const pagination = Object.assign({},dataState.pagination);
const filters: any = {};
pagination.filters = tableState.filters;
this.updateState({...STATE, pagination});
}
nextPage(): void {
const state = this.store.getValue();
const pagination: Paginator = {
after: state.transactions[state.transactions.length - 1],
before: undefined,
limit: state.pagination.limit,
};
console.log(pagination);
this.updateState({...STATE, ...pagination});
}
previousPage(): void {
const state = this.store.getValue();
const pagination: Paginator = {
before: state.transactions[0],
after: undefined,
limit: state.pagination.limit,
};
console.log(pagination);
this.updateState({...STATE, pagination});
}
updatePageLimit(limit: number): void {
let pagination = this.store.getValue().pagination;
pagination = {...pagination, limit};
this.updateState({...STATE, pagination});
}
private updateState(state: TransactionState): void {
this.store.next((STATE = {...state}));
}
ngOnInit(): void {
}
}