columnMode="flex"
[toolHeader]="false"
[autoReload]="autoReload"
+ [customCss]="customCss"
[autoSave]="false"
[header]="false"
[footer]="false"
import { configureTestBed } from '../../../../testing/unit-test-helper';
import { ComponentsModule } from '../../components/components.module';
+import { CellTemplate } from '../../enum/cell-template.enum';
+import { CdTableColumn } from '../../models/cd-table-column';
import { TableComponent } from '../table/table.component';
import { TableKeyValueComponent } from './table-key-value.component';
});
it('should create', () => {
+ fixture.detectChanges();
expect(component).toBeTruthy();
});
]);
});
});
+
+ describe('columns set up', () => {
+ let columns: CdTableColumn[];
+
+ beforeEach(() => {
+ columns = [
+ {
+ prop: 'key',
+ flexGrow: 1,
+ cellTransformation: CellTemplate.bold
+ },
+ {
+ prop: 'value',
+ flexGrow: 3
+ }
+ ];
+ });
+
+ it('should have the following default column set up', () => {
+ component.ngOnInit();
+ expect(component.columns).toEqual(columns);
+ });
+
+ it('should have the following column set up if customCss is defined', () => {
+ component.customCss = {
+ 'answer-of-everything': 42
+ };
+ component.ngOnInit();
+ columns[1].cellTransformation = CellTemplate.classAdding;
+ expect(component.columns).toEqual(columns);
+ });
+ });
});
@Input()
hideEmpty = false;
+ // If set, the classAddingTpl is used to enable different css for different values
+ @Input()
+ customCss?: { [css: string]: number | string | ((any) => boolean) };
+
columns: Array<CdTableColumn> = [];
tableData: Item[];
flexGrow: 3
}
];
+ if (this.customCss) {
+ this.columns[1].cellTransformation = CellTemplate.classAdding;
+ }
// We need to subscribe the 'fetchData' event here and not in the
// HTML template, otherwise the data table will display the loading
// indicator infinitely if data is only bound via '[data]="xyz"'.
[hidden]="!value"></i>
</ng-template>
-
<ng-template #perSecondTpl
let-row="row"
let-value="value">
<span *ngIf="row.cdExecuting"
class="text-muted italic">({{ row.cdExecuting }}... )</span>
</ng-template>
+
+<ng-template #classAddingTpl
+ let-value="value">
+ <span class="{{useCustomClass(value)}}">{{ value }}</span>
+</ng-template>
clearLocalStorage();
});
});
+
+ describe('useCustomClass', () => {
+ beforeEach(() => {
+ component.customCss = {
+ 'label label-danger': 'active',
+ 'secret secret-number': 123.456,
+ 'btn btn-sm': (v) => _.isString(v) && v.startsWith('http'),
+ secure: (v) => _.isString(v) && v.startsWith('https')
+ };
+ });
+
+ const expectUseCustomClass = (values: any[], expectation: string) => {
+ values.forEach((value) => expect(component.useCustomClass(value)).toBe(expectation));
+ };
+
+ it('should throw an error if custom classes are not set', () => {
+ component.customCss = undefined;
+ expect(() => component.useCustomClass('active')).toThrowError('Custom classes are not set!');
+ });
+
+ it('should not return any class', () => {
+ expectUseCustomClass(['', 'something', 123, { complex: 1 }, [1, 2, 3]], undefined);
+ });
+
+ it('should match a string and return the corresponding class', () => {
+ expect(component.useCustomClass('active')).toBe('label label-danger');
+ });
+
+ it('should match a number and return the corresponding class', () => {
+ expect(component.useCustomClass(123.456)).toBe('secret secret-number');
+ });
+
+ it('should match against a function and return the corresponding class', () => {
+ expect(component.useCustomClass('http://no.ssl')).toBe('btn btn-sm');
+ });
+
+ it('should match against multiple functions and return the corresponding classes', () => {
+ expect(component.useCustomClass('https://secure.it')).toBe('btn btn-sm secure');
+ });
+ });
});
perSecondTpl: TemplateRef<any>;
@ViewChild('executingTpl')
executingTpl: TemplateRef<any>;
+ @ViewChild('classAddingTpl')
+ classAddingTpl: TemplateRef<any>;
// This is the array with the items to be shown.
@Input()
@Input()
autoSave = true;
+ // Only needed to set if the classAddingTpl is used
+ @Input()
+ customCss?: { [css: string]: number | string | ((any) => boolean) };
+
/**
* Should be a function to update the input data if undefined nothing will be triggered
*
this.cellTemplates.routerLink = this.routerLinkTpl;
this.cellTemplates.perSecond = this.perSecondTpl;
this.cellTemplates.executing = this.executingTpl;
+ this.cellTemplates.classAdding = this.classAddingTpl;
+ }
+
+ useCustomClass(value: any): string {
+ if (!this.customCss) {
+ throw new Error('Custom classes are not set!');
+ }
+ const classes = Object.keys(this.customCss);
+ const css = Object.values(this.customCss)
+ .map((v, i) => ((_.isFunction(v) && v(value)) || v === value) && classes[i])
+ .filter((x) => x)
+ .join(' ');
+ return (!_.isEmpty(css) && css) || undefined;
}
ngOnChanges(changes) {
perSecond = 'perSecond',
checkIcon = 'checkIcon',
routerLink = 'routerLink',
- executing = 'executing'
+ executing = 'executing',
+ classAdding = 'classAdding'
}