【发布时间】:2021-01-02 18:51:36
【问题描述】:
我正在使用共价来实现 augular 的表格。
vrp-table-component html 像这样:
<span *ngIf="selectedRows?.length && selectable" class="push-left-sm">
<span class="md-body-1">{{selectedRows?.length}} item(s) selected
<span *ngFor="let a of selectActions">
<button *ngIf="a.haspermission" mat-icon-button color='warn' [matTooltip]=" a.tooltip||a.label"
(click)="(a.click(selectedRows)) ? undefined: (cancelSelection())">
<mat-icon>{{a.icon}}</mat-icon>
</button>
</span>
<button mat-icon-button matTooltip="Cancel selection" (click)="cancelSelection()">
<mat-icon>close</mat-icon>
</button>
</span>
</span>
<ng-template [ngForOf]='tableActions' ngFor let-b>
<button mat-button color="accent" *ngIf='b.menuTemplateRef && b.haspermission'
[matMenuTriggerFor]="b.menuTemplateRef()">
<mat-icon *ngIf='b.icon'>{{b.icon}}</mat-icon>{{b.label||''}}
</button>
<button mat-icon-button *ngIf='!b.menuTemplateRef && b.haspermission' [matTooltip]='b.tooltip || b.label'
(click)='b.click()'>
<mat-icon *ngIf='b.icon'>{{b.icon}}</mat-icon>{{b.label||''}}
</button>
</ng-template>
<button mat-icon-button matTooltip='Select Columns' (click)='filterColumns()' *ngIf='showSelectColumns'>
<mat-icon>filter_list</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<td-data-table #dataTable [data]="filteredData" [columns]="columns" [selectable]="selectable"
[clickable]="clickable" [multiple]="multiple" [sortable]="sortable" [sortBy]="sortBy" [(ngModel)]="selectedRows"
[sortOrder]="sortOrder" (sortChange)="onSort($event)" (rowClick)='editRow.emit($event.row)'
(selectAll)="onSelectAny()" (rowSelect)="onSelectAny()" [style.height.px]="dataTable.hasData?tableHeight:50"
[style.min-width]="dataTable.hasData?(columns.length * minWidthFactor + 'px'):'auto'">
<ng-template tdDataTableTemplate="_itemActions" let-value="value" let-row="row" let-column="column">
<span *ngFor="let a of itemActions">
<button mat-icon-button *ngIf="a.haspermission" (click)="a.click(row)"
[matTooltip]='a.tooltip || a.label'>
<mat-icon>{{a.icon}}</mat-icon>
</button>
</span>
<span *ngIf='itemMenu && itemMenu.length > 0'>
<button mat-icon-button [matMenuTriggerFor]="menuDetail">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu [overlapTrigger]="false" #menuDetail="matMenu">
<span *ngFor="let a of itemMenu">
<a mat-menu-item (click)="a.click(row)" *ngIf="a.haspermission">
<mat-icon *ngIf='a.icon'>{{a.icon}}</mat-icon>{{a.label}}
</a>
</span>
</mat-menu>
</span>
</ng-template>
<ng-template tdDataTableTemplate="_error" let-value="value" let-row="row" let-column="column">
<div layout='column'>
<span *ngFor='let i of value'><strong>{{i[0]}}:</strong> {{i[1]}} </span>
</div>
</ng-template>
</td-data-table>
<div *ngIf="filteredData && filteredData.length===0" layout="row" layout-align="center center">
<h3>No data to display.</h3>
</div>
和这样的 vrp-table-component.ts :
private _customFilteredData: any[];
// placeholders for the callbacks which are later provided by the Control Value Accessor
private _onTouchedCallback: () => void = noOp;
private _onChangeCallback: (_: any) => void = noOp;
@Input() id: string;
@Input() columns: any[] = [];
@Input() data: any[] = [];
@Input() requiredData: any[] = []; // list of data that cannot be un-selected
@Input() tableActions: any[] = [];
@Input() selectActions: any[] = [{ label: 'Delete', icon: 'delete', click: (items) => this.deleteItems(items) }];
@Input() minWidthFactor: number = 60;
@Input() showSelectColumns: boolean = true;
@Input() itemActions: any[] = [];
@Input() itemMenu: any[] = [];
@Input() sortBy: string;
@Input() tableTitle: string = undefined;
_dataTableService = new TdDataTableService();
filteredData: any[];
filteredTotal: number;
searchTerm: string = '';
refreshTimeout: any;
selectedRows: any[] = [];
sortOrder: TdDataTableSortingOrder = TdDataTableSortingOrder.Descending;
@Input() sortable: boolean = true;
@Input() clickable: boolean = true;
@Input() selectable: boolean = true;
@Input() multiple: boolean = true;
@Input() editable: boolean = true;
@Input() tableHeight: number = 500;
@Output() editRow: EventEmitter<any> = new EventEmitter();
@Output() deleteRow: EventEmitter<any> = new EventEmitter();
@ViewChild('dataTable') dataTable;
@ViewChild('searchBox') searchBox;
@Input() set value(v: any) {
this.selectedRows = v;
this._onChangeCallback(v);
}
constructor(
private _dialog: VrpDialogService,
) { }
get value(): any { return this.selectedRows; }
writeValue(value: any) { // required by ControlValueAccessor interface
if (value !== this.selectedRows) {
this.selectedRows = value;
}
}
registerOnChange(fn: any) { // required by ControlValueAccessor interface
this._onChangeCallback = fn;
}
registerOnTouched(fn: any) { // required by ControlValueAccessor interface
this._onTouchedCallback = fn;
}
ngOnChanges(changes: SimpleChanges) {
if (this.itemMenu) {
this.itemMenu = this.itemMenu.filter((im) => im.haspermission === true).length === 0 ? [] : this.itemMenu;
}
if (changes.columns && this.columns) {
this._loadValuesToSessionStorage();
}
this.filter();
}
cancelSelection() {
this.selectedRows = [];
this._onChangeCallback(this.selectedRows);
this._selectRequiredData();
}
filterColumns() {
let formElements = this.columns.map((c, index) => ({ name: `c_${index}`, label: c.label, type: 'checkbox', default: !c.hidden }));
// hide Column ID in Table SMS Template
if (this.id === 'tablePlannerData_SMSTemplate') {
const columns = formElements;
formElements = [];
columns.forEach((column) => {
if (column.label !== 'Id') {
formElements.push(column);
}
});
}
this._dialog.openDynamicEdit(formElements, undefined, 'Select columns')
.subscribe((answer) => {
if (answer) {
this.columns.forEach((c, index) => {
c.hidden = !answer['c_' + index] && c.label !== '';
});
this._saveValuesToSessionStorage();
this.filter(this._customFilteredData);
this.refresh();
}
});
}
deleteItems(items) {
_remove(this.data, (d) => items.indexOf(d) !== -1);
this.deleteRow.emit(items);
this.cancelSelection();
this.filter(this._customFilteredData);
}
onSort(sortEvent: ITdDataTableSortChangeEvent): void {
this.sortBy = sortEvent.name;
this.sortOrder = sortEvent.order;
this.filter(this._customFilteredData);
}
onSelectAny(): void {
this._selectRequiredData();
}
@HostListener('window:resize', ['$event'])
onResize(event) {
if (this.refreshTimeout) {
clearTimeout(this.refreshTimeout);
}
this.refreshTimeout = setTimeout(() => {
this.refresh();
}, 1000);
}
search(searchTerm: string): void {
this.searchTerm = searchTerm.trim();
this.filter(this._customFilteredData);
}
clearSearchField() {
this.searchBox.value = '';
}
filter(customFilteredData: any[] = undefined): void {
this._customFilteredData = customFilteredData;
if (!this.columns || !this.data) {
return;
}
const excludedColumns: string[] = this.columns
.filter((column: ITdDataTableColumn) => {
return (((column.filter === undefined && column.hidden === true) ||
(column.filter !== undefined && column.filter === false)));
}).map((column: ITdDataTableColumn) => column.name);
let newData: any[] = this.data;
if (newData.length > 0) {
if (!this._customFilteredData) {
newData = this._dataTableService.filterData(newData, this.searchTerm, true, excludedColumns);
} else {
newData = this._dataTableService.filterData(this._customFilteredData, this.searchTerm, true, excludedColumns);
}
if (this.sortBy) {
newData = _sortBy(newData, this.sortBy);
if (this.sortOrder === TdDataTableSortingOrder.Descending) {
newData.reverse();
}
}
this.filteredTotal = newData.length;
} else {
this.filteredTotal = 0;
}
this.filteredData = newData;
// select/unselect only the filtered data
// this.selectedRows = this.selectedRows.filter((r) => this.filteredData.includes(r));
this._selectRequiredData();
this._onChangeCallback(this.selectedRows);
}
refresh() {
this.dataTable.refresh();
}
private _selectRequiredData() {
if (!this.requiredData || this.requiredData.length === 0) {
return;
}
// add missing list of required data (i.e. cannot be unselected) back to selection list
const missingRequiredData = _differenceWith(this.requiredData, this.selectedRows, _isEqual);
this.selectedRows.push(...missingRequiredData);
}
private _loadValuesToSessionStorage() {
if (this.id) {
try {
const defaultValues: boolean[] = JSON.parse(sessionStorage.getItem(this.id));
if (defaultValues) {
this.columns.forEach((c, i) => { if (c.name !== '_itemActions') { c.hidden = defaultValues[i]; } });
}
} catch (err) {
console.trace(`Can load Table ${this.id} from sessionStorage`);
}
}
}
private _saveValuesToSessionStorage() {
if (this.id) {
try {
const defaultValues: boolean[] = this.columns.map((c) => c.hidden);
sessionStorage.setItem(this.id, JSON.stringify(defaultValues));
} catch (err) {
console.trace(`Can save Table ${this.id} to sessionStorage`);
}
}
}
}
调用vrp-table的代码如下:
<vrp-table
#vrpTable id='storePortal' [columns]="columns" [data]="allDeliveryDetailsRecords" [tableHeight]="tableHeight"
[itemMenu]='tableItemMenus' [itemActions]='tableItemActions' [tableActions]='tableActions' selectable=false></vrp-table>
效果如下:
但是,我想为奇数行/偶数行设置不同颜色的行。我该怎么办?
谁能给我一些建议?
【问题讨论】:
-
如何制作背景为白色的奇数行,但背景为蓝色的偶数行?非常感谢。
标签: angular