Background
主从表结构,有时为了方便数据呈现,在UI上不显示从表资料,那么需要动态把从表的资料加载到主表的固定栏位上。
例如:主表是人员信息,从表是银行卡信息,一个人在同一家银行可能有多张银行卡,且一个人可能在多家银行开户。
How to implement?
1. Provided data list of person and bank account informaciton
a. Person information
personData: any[] = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park'
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park'
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park'
}
];
b. Bank list
banks = [
{ code: 'icbc', name: '工行' },
{ code: 'abc', name: '农行' },
{ code: 'ccb', name: '建行' },
{ code: 'bocom', name: '交行' },
{ code: 'boc', name: '中行' }
];
c. Bank account list
bankAccounts: BankAccount[] = [
{ key: '1', account: '1-工行001', bank: 'icbc' },
{ key: '2', account: '2-交行001', bank: 'bocom' },
{ key: '3', account: '3-建行001', bank: 'ccb' },
{ key: '3', account: '3-农行001', bank: 'abc' },
{ key: '1', account: '1-农行001', bank: 'abc' },
{ key: '1', account: '1-农行002', bank: 'abc' },
{ key: '2', account: '2-工行001', bank: 'icbc' },
{ key: '1', account: '1-工行002', bank: 'icbc' }
];
2. Interface
a. Person
interface Person {
key: string;
name: string;
age: number;
address: string;
icbc: string;
abc: string;
ccb: string;
bocom: string;
boc: string;
}
b. Bank account
interface BankAccount {
key: string;
account: string;
bank: string;
}
3. Implementation method
const refList = this.bankAccounts;
const refType = this.banks;
// 循环主表
for (let item of this.personData) {
//循环从表需显示在主表呈现的类型
refType.forEach(typ => {
const accoutsOfBank = refList.filter(o => o.key === item.key && o.bank === typ.code); //[{}]
let accounts = '';
// 按从表类型把资料合并
for (const element of accoutsOfBank) {
accounts += `${element.account};`;
}
// 根据从表类型,把合并的资料更新至主表固定栏位上
switch (typ.code) {
case 'icbc':
item.icbc = accounts;
break;
case 'abc':
item.abc = accounts;
break;
case 'ccb':
item.ccb = accounts;
break;
case 'bocom':
item.bocom = accounts;
break;
case 'boc':
item.boc = accounts;
break;
default:
break;
}
});
}
4. The full source code
import { NgFor } from '@angular/common';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { NzDividerModule } from 'ng-zorro-antd/divider';
import { NzTableModule } from 'ng-zorro-antd/table';
interface Person {
key: string;
name: string;
age: number;
address: string;
icbc: string;
abc: string;
ccb: string;
bocom: string;
boc: string;
}
interface BankAccount {
key: string;
account: string;
bank: string;
}
@Component({
selector: 'app-pages-sample-master-detail',
template: `
<p>
主从表结构,有时为了方便数据呈现,在UI上不显示从表资料,那么需要动态把从表的资料加载到主表的固定栏位上。
例如:主表是人员信息,从表是银行卡信息,一个人在同一家银行可能有多张银行卡,且一个人可能在多家银行开户。
</p>
<nz-table #basicTable [nzData]="personData">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Address</th>
<th *ngFor="let bank of banks">{{ bank.name }}</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of basicTable.data">
<td>{{ data.name }}</td>
<td>{{ data.age }}</td>
<td>{{ data.address }}</td>
<td>{{ data.icbc }}</td>
<td>{{ data.abc }}</td>
<td>{{ data.ccb }}</td>
<td>{{ data.bocom }}</td>
<td>{{ data.boc }}</td>
<td>
<a>Action 一 {{ data.name }}</a>
<nz-divider nzType="vertical"></nz-divider>
<a>Delete</a>
</td>
</tr>
</tbody>
</nz-table>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
providers: [],
imports: [NzTableModule, NzDividerModule, NgFor]
})
export class MasterDetailComponent implements OnInit {
personData: any[] = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park'
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park'
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park'
}
];
banks = [
{ code: 'icbc', name: '工行' },
{ code: 'abc', name: '农行' },
{ code: 'ccb', name: '建行' },
{ code: 'bocom', name: '交行' },
{ code: 'boc', name: '中行' }
];
bankAccounts: BankAccount[] = [
{ key: '1', account: '1-工行001', bank: 'icbc' },
{ key: '2', account: '2-交行001', bank: 'bocom' },
{ key: '3', account: '3-建行001', bank: 'ccb' },
{ key: '3', account: '3-农行001', bank: 'abc' },
{ key: '1', account: '1-农行001', bank: 'abc' },
{ key: '1', account: '1-农行002', bank: 'abc' },
{ key: '2', account: '2-工行001', bank: 'icbc' },
{ key: '1', account: '1-工行002', bank: 'icbc' }
];
constructor() {}
ngOnInit(): void {
const refList = this.bankAccounts;
const refType = this.banks;
// 循环主表
for (let item of this.personData) {
//循环从表需显示在主表呈现的类型
refType.forEach(typ => {
const accoutsOfBank = refList.filter(o => o.key === item.key && o.bank === typ.code); //[{}]
let accounts = '';
// 按从表类型把资料合并
for (const element of accoutsOfBank) {
accounts += `${element.account};`;
}
// 根据从表类型,把合并的资料更新至主表固定栏位上
switch (typ.code) {
case 'icbc':
item.icbc = accounts;
break;
case 'abc':
item.abc = accounts;
break;
case 'ccb':
item.ccb = accounts;
break;
case 'bocom':
item.bocom = accounts;
break;
case 'boc':
item.boc = accounts;
break;
default:
break;
}
});
}
console.log(this.personData);
}
}
5. Test result