[AAE-7817] Show hide columns on datatable (#7580)

* [AAE-7817]  Show hide columns for data-table

* Update

* update tests and uses material harness

* added pipes test

* update

* update

* added tests for datatable

* update

* Added documentation

* Fix for drop column header

* lint fix

* fix lint
This commit is contained in:
Bartosz Sekuła
2022-05-10 19:09:26 +02:00
committed by GitHub
parent 3a5daf960c
commit 7629797408
25 changed files with 862 additions and 34 deletions

View File

@@ -0,0 +1,52 @@
<div class="adf-columns-selector" (click)="$event.stopPropagation();">
<div class="adf-columns-selector-header">
<span class="adf-columns-selector-header-label">
{{"ADF-DATATABLE.COLUMNS_SELECTOR.COLUMNS" | translate}}
</span>
<button mat-icon-button (click)="closeMenu()">
<mat-icon>close</mat-icon>
</button>
</div>
<mat-divider class="adf-columns-selector-divider"></mat-divider>
<div class="adf-columns-selector-search-input-container">
<mat-icon
class="adf-columns-selector-search-input-icon">
search
</mat-icon>
<input
[formControl]="searchInputControl"
class="adf-columns-selector-search-input"
type="text"
[placeholder]='"ADF-DATATABLE.COLUMNS_SELECTOR.SEARCH" | translate'>
</div>
<ng-container *ngFor="let column of columnItems">
<div
*ngIf="(column.title | translate | filterString:searchQuery) as translatedTitle"
class="adf-columns-selector-list-item-container">
<mat-checkbox
color="primary"
class="adf-columns-selector-column-checkbox"
[attr.data-automation-id]="'adf-columns-selector-column-checkbox-' + column.title"
[checked]="!column.isHidden"
(change)="changeColumnVisibility(column)">
<div class="adf-columns-selector-list-content">{{translatedTitle}}</div>
</mat-checkbox>
</div>
</ng-container>
<mat-divider class="adf-columns-selector-divider"></mat-divider>
<div class="adf-columns-selector-footer">
<button
mat-flat-button
color="primary"
(click)="apply()">
{{"ADF-DATATABLE.COLUMNS_SELECTOR.APPLY" | translate}}
</button>
</div>
</div>

View File

@@ -0,0 +1,87 @@
$adf-columns-selector-space: 12px;
@mixin adf-columns-selector-side-padding {
padding: 0 $adf-columns-selector-space;
}
@mixin adf-columns-selector-top-bottom-padding {
padding: $adf-columns-selector-space 0;
}
.adf-columns-selector {
@include adf-columns-selector-top-bottom-padding;
min-width: 277px;
&-header {
@include adf-columns-selector-side-padding;
display: flex;
justify-content: space-between;
align-items: center;
}
&-header-label {
font-size: var(--theme-body-1-font-size);
}
&-list-item-container {
margin-top: 10px;
&:hover {
background-color: var(--theme-bg-hover-color);
}
}
&-list-content {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
width: 210px;
}
&-column-checkbox {
padding: 0 20px;
}
&-footer {
@include adf-columns-selector-side-padding;
display: flex;
justify-content: flex-end;
}
&-divider {
margin: 16px 0;
}
&-search-input-container {
@include adf-columns-selector-side-padding;
position: relative;
display: flex;
align-items: center;
margin-bottom: 15px;
}
&-search-input {
padding: 10px 10px 10px 29px;
width: 100%;
outline: 0;
border-radius: 6px;
border: 1px solid var(--theme-background-color);
background: var(--theme-background-color);
:focus {
outline: none !important;
}
}
&-search-input-icon {
position: absolute;
left: 17px;
top: 10px;
font-size: var(--theme-adf-icon-1-font-size);
}
}

View File

@@ -0,0 +1,162 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { ColumnsSelectorComponent } from './columns-selector.component';
import { DataColumn } from '../../data/data-column.model';
import { Observable, Subject } from 'rxjs';
import { MatMenuTrigger } from '@angular/material/menu';
import { CoreTestingModule } from 'core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { By } from '@angular/platform-browser';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { HarnessLoader } from '@angular/cdk/testing';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
describe('ColumnsSelectorComponent', () => {
let fixture: ComponentFixture<ColumnsSelectorComponent>;
let loader: HarnessLoader;
let component: ColumnsSelectorComponent;
let inputColumns: DataColumn[] = [];
const menuOpenedTrigger = new Subject<void>();
const menuClosedTrigger = new Subject<void>();
let mainMenuTrigger: { menuOpened: Observable<void>; menuClosed: Observable<void> };
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
CoreTestingModule
],
declarations: [ColumnsSelectorComponent]
}).compileComponents();
fixture = TestBed.createComponent(ColumnsSelectorComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
component = fixture.componentInstance;
inputColumns = [{
id: 'id0',
key: 'key0',
title: 'title0',
type: 'text'
}, {
id: 'id1',
key: 'key1',
title: 'title1',
type: 'text'
}, {
id: 'id2',
key: 'key2',
title: 'title2',
type: 'text'
}, {
id: 'id3',
key: 'NoTitle',
type: 'text'
}, {
id: 'id4',
key: 'IsHidden',
type: 'text',
title: 'title4',
isHidden: true
}];
mainMenuTrigger = {
menuOpened: menuOpenedTrigger.asObservable(),
menuClosed: menuClosedTrigger.asObservable()
};
component.columns = inputColumns;
component.mainMenuTrigger = mainMenuTrigger as MatMenuTrigger;
fixture.detectChanges();
});
it('should clear search after closing menu', fakeAsync(() => {
menuOpenedTrigger.next();
fixture.detectChanges();
let searchInput = fixture.debugElement.query(By.css('.adf-columns-selector-search-input')).nativeElement;
searchInput.value = 'TEST';
searchInput.dispatchEvent(new Event('input'));
tick(300);
expect(searchInput.value).toBe('TEST');
menuClosedTrigger.next();
tick(300);
searchInput = fixture.debugElement.query(By.css('.adf-columns-selector-search-input')).nativeElement;
expect(searchInput.value).toBe('');
}));
it('should list only columns with title', async () => {
menuOpenedTrigger.next();
fixture.detectChanges();
const checkboxes = await loader.getAllHarnesses(MatCheckboxHarness);
expect(checkboxes.length).toBe(4);
expect(await checkboxes[0].getLabelText()).toBe(inputColumns[0].title);
expect(await checkboxes[1].getLabelText()).toBe(inputColumns[1].title);
expect(await checkboxes[2].getLabelText()).toBe(inputColumns[2].title);
expect(await checkboxes[3].getLabelText()).toBe(inputColumns[4].title);
});
it('should filter columns by search text', fakeAsync(async () => {
fixture.detectChanges();
menuOpenedTrigger.next();
const searchInput = fixture.debugElement.query(By.css('.adf-columns-selector-search-input')).nativeElement;
searchInput.value = inputColumns[0].title;
searchInput.dispatchEvent(new Event('input'));
tick(400);
fixture.detectChanges();
const columnCheckboxes = await loader.getAllHarnesses(MatCheckboxHarness);
expect(columnCheckboxes.length).toBe(1);
expect(await columnCheckboxes[0].getLabelText()).toBe(inputColumns[0].title);
}));
it('should change column visibility', async () => {
menuOpenedTrigger.next();
fixture.detectChanges();
const firstColumnCheckbox = await loader.getHarness(MatCheckboxHarness);
await firstColumnCheckbox.toggle();
expect(component.columnItems[0].isHidden).toBe(true);
});
it('should set proper default state for checkboxes', async () => {
menuOpenedTrigger.next();
fixture.detectChanges();
const checkboxes = await loader.getAllHarnesses(MatCheckboxHarness);
expect(await checkboxes[0].isChecked()).toBe(true);
expect(await checkboxes[1].isChecked()).toBe(true);
expect(await checkboxes[2].isChecked()).toBe(true);
expect(await checkboxes[3].isChecked()).toBe(false);
});
});

View File

@@ -0,0 +1,83 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { FormControl } from '@angular/forms';
import { MatMenuTrigger } from '@angular/material/menu';
import { Subject } from 'rxjs';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { DataColumn } from '../../data/data-column.model';
@Component({
selector: 'adf-datatable-column-selector',
templateUrl: './columns-selector.component.html',
styleUrls: ['./columns-selector.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ColumnsSelectorComponent implements OnInit, OnDestroy {
@Input()
columns: DataColumn[] = [];
@Input()
mainMenuTrigger: MatMenuTrigger;
@Output()
submitColumnsVisibility = new EventEmitter<DataColumn[]>();
onDestroy$ = new Subject();
columnItems: DataColumn[] = [];
searchInputControl = new FormControl('');
searchQuery = '';
ngOnInit(): void {
this.mainMenuTrigger.menuOpened.pipe(
takeUntil(this.onDestroy$)
).subscribe(() => {
this.columnItems = this.columns.map(column => ({...column}));
});
this.mainMenuTrigger.menuClosed.pipe(
takeUntil(this.onDestroy$)
).subscribe(() => {
this.searchInputControl.setValue('');
});
this.searchInputControl.valueChanges.pipe(
debounceTime(300),
takeUntil(this.onDestroy$)
).subscribe((searchQuery) => {
this.searchQuery = searchQuery;
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
closeMenu(): void {
this.mainMenuTrigger.closeMenu();
}
changeColumnVisibility(column: DataColumn): void {
column.isHidden = !column.isHidden;
}
apply(): void {
this.submitColumnsVisibility.emit(this.columnItems);
this.closeMenu();
}
}

View File

@@ -27,7 +27,9 @@
</div>
<div class="adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-header"
*ngFor="let col of data.getColumns(); let columnIndex = index"
*ngFor="
let col of (data.getColumns() | filterOutEvery:'isHidden':true);
let columnIndex = index"
[class.adf-sortable]="col.sortable"
[attr.data-automation-id]="'auto_id_' + col.key"
[class.adf-datatable__header--sorted-asc]="isColumnSorted(col, 'asc')"
@@ -93,10 +95,31 @@
<div class="adf-drop-header-cell-placeholder" *cdkDragPlaceholder></div>
</div>
<!-- Actions (right) -->
<div *ngIf="actions && actionsPosition === 'right'" class="adf-actions-column adf-datatable-cell-header adf-datatable__actions-cell">
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
<!-- Header actions (right) -->
<div
*ngIf="actions && actionsPosition === 'right' || mainActionTemplate"
class="adf-actions-column adf-datatable-cell-header adf-datatable__actions-cell"
>
<ng-container *ngIf="mainActionTemplate">
<button
mat-icon-button
#mainMenuTrigger="matMenuTrigger"
[matMenuTriggerFor]="mainMenu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #mainMenu>
<ng-container
[ngTemplateOutlet]="mainActionTemplate"
[ngTemplateOutletContext]="{
$implicit: mainMenuTrigger
}">
</ng-container>
</mat-menu>
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
</ng-container>
</div>
</adf-datatable-row>
<mat-form-field *ngIf="display === 'gallery' && isHeaderVisible()">
<mat-select [value]="getSortingKey()" [attr.data-automation-id]="'grid-view-sorting'">
@@ -156,7 +179,7 @@
{{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_FILE' | translate }}
</mat-checkbox>
</div>
<div *ngFor="let col of data.getColumns()"
<div *ngFor="let col of (data.getColumns() | filterOutEvery:'isHidden':true);"
role="gridcell"
class="adf-datatable-cell adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}}"
[attr.title]="col.title | translate"
@@ -262,28 +285,31 @@
</div>
</div>
<!-- Actions (right) -->
<div *ngIf="actions && actionsPosition === 'right'"
<!-- Row actions (right) -->
<div *ngIf="(actions && actionsPosition === 'right') || mainActionTemplate"
role="gridcell"
class="adf-datatable-cell adf-datatable__actions-cell adf-datatable-center-actions-column-ie">
<button mat-icon-button [matMenuTriggerFor]="menu" #actionsMenuTrigger="matMenuTrigger"
[ngClass]="getHideActionsWithoutHoverClass(actionsMenuTrigger)"
[attr.aria-label]="'ADF-DATATABLE.ACCESSIBILITY.ROW_OPTION_BUTTON' | translate"
[title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate"
[attr.id]="'action_menu_right_' + idx"
[attr.data-automation-id]="'action_menu_' + idx">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item *ngFor="let action of getRowActions(row)"
[attr.data-automation-id]="action.title"
[attr.aria-label]="action.title | translate"
[disabled]="action.disabled"
(click)="onExecuteRowAction(row, action)">
<mat-icon *ngIf="action.icon">{{ action.icon }}</mat-icon>
<span>{{ action.title | translate }}</span>
<ng-container *ngIf="(actions && actionsPosition === 'right')">
<button mat-icon-button [matMenuTriggerFor]="menu" #actionsMenuTrigger="matMenuTrigger"
[ngClass]="getHideActionsWithoutHoverClass(actionsMenuTrigger)"
[attr.aria-label]="'ADF-DATATABLE.ACCESSIBILITY.ROW_OPTION_BUTTON' | translate"
[title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate"
[attr.id]="'action_menu_right_' + idx"
[attr.data-automation-id]="'action_menu_' + idx">
<mat-icon>more_vert</mat-icon>
</button>
</mat-menu>
<mat-menu #menu="matMenu">
<button mat-menu-item *ngFor="let action of getRowActions(row)"
[attr.data-automation-id]="action.title"
[attr.aria-label]="action.title | translate"
[disabled]="action.disabled"
(click)="onExecuteRowAction(row, action)">
<mat-icon *ngIf="action.icon">{{ action.icon }}</mat-icon>
<span>{{ action.title | translate }}</span>
</button>
</mat-menu>
</ng-container>
</div>
</adf-datatable-row>
<div *ngIf="isEmpty()"

View File

@@ -1720,3 +1720,70 @@ describe('Drag&Drop column header', () => {
expect(headerCells[1].innerText).toBe(dataTableSchema[0].title);
});
});
describe('Show/hide columns', () => {
let fixture: ComponentFixture<DataTableComponent>;
let dataTable: DataTableComponent;
let data: DataColumn[] = [];
let dataTableSchema: DataColumn[] = [];
setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreTestingModule
],
declarations: [CustomColumnTemplateComponent],
schemas: [NO_ERRORS_SCHEMA]
});
beforeEach(() => {
fixture = TestBed.createComponent(DataTableComponent);
dataTable = fixture.componentInstance;
data = [
{ id: '1', title: 'name1', key: 'key', type: 'text' },
{ id: '2', title: 'name1', key: 'key', type: 'text' },
{ id: '3', title: 'name1', key: 'key', type: 'text' }
];
dataTableSchema = [
new ObjectDataColumn({ key: 'id', title: 'ID' }),
new ObjectDataColumn({ key: 'name', title: 'Name'}),
new ObjectDataColumn({ key: 'status', title: 'status', isHidden: true })
];
dataTable.data = new ObjectDataTableAdapter(
[...data],
[...dataTableSchema]
);
fixture.detectChanges();
});
it('should hide columns with isHidden prop', () => {
const headerCells = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell--text.adf-datatable-cell-header');
expect(headerCells.length).toBe(2);
});
it('should reload columns after changing columns visibility', () => {
const columns = [
new ObjectDataColumn({ key: 'id', title: 'ID' }),
new ObjectDataColumn({ key: 'name', title: 'Name', isHidden: true }),
new ObjectDataColumn({ key: 'status', title: 'status', isHidden: true })
];
dataTable.ngOnChanges({
columns: {
previousValue: undefined,
currentValue: columns,
firstChange: false,
isFirstChange: () => false
}
});
fixture.detectChanges();
const headerCells = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell--text.adf-datatable-cell-header');
expect(headerCells.length).toBe(1);
});
});

View File

@@ -104,6 +104,10 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
@Input()
multiselect: boolean = false;
/** Toggles main data table action column. */
@Input()
mainTableAction: boolean = true;
/** Toggles the data actions column. */
@Input()
actions: boolean = false;
@@ -200,6 +204,7 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
noContentTemplate: TemplateRef<any>;
noPermissionTemplate: TemplateRef<any>;
loadingTemplate: TemplateRef<any>;
mainActionTemplate: TemplateRef<any>;
isSelectAllIndeterminate: boolean = false;
isSelectAllChecked: boolean = false;
@@ -313,10 +318,16 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
}
onDropHeaderColumn(event: CdkDragDrop<unknown>): void {
const columns = this.data.getColumns();
moveItemInArray(columns, event.previousIndex, event.currentIndex);
const allColumns = this.data.getColumns();
const shownColumns = allColumns.filter(column => !column.isHidden);
const hiddenColumns = allColumns.filter(column => column.isHidden);
moveItemInArray(shownColumns, event.previousIndex, event.currentIndex);
const allColumnsWithNewOrder = [...shownColumns, ...hiddenColumns];
this.setTableColumns(allColumnsWithNewOrder);
this.columnOrderChanged.emit(allColumnsWithNewOrder);
this.columnOrderChanged.emit(columns);
this.isDraggingHeaderColumn = false;
}

View File

@@ -46,4 +46,5 @@ export interface DataColumn {
sortingKey?: string;
header?: TemplateRef<any>;
draggable?: boolean;
isHidden?: boolean;
}

View File

@@ -38,6 +38,9 @@ export abstract class DataTableSchema {
protected columnsOrder: string[] | undefined;
protected columnsOrderedByKey: string = 'id';
protected hiddenColumns: string[] | undefined;
protected hiddenColumnsKey: string = 'id';
private layoutPresets = {};
private columnsSchemaSubject$ = new ReplaySubject<boolean>();
@@ -59,7 +62,8 @@ export abstract class DataTableSchema {
}
public createColumns(): void {
const columns = this.mergeJsonAndHtmlSchema();
const allColumns = this.mergeJsonAndHtmlSchema();
const columns = this.setHiddenColumns(allColumns);
this.columns = this.sortColumnsByKey(columns);
}
@@ -127,4 +131,19 @@ export abstract class DataTableSchema {
return [...columnsWithProperOrder, ...defaultColumns];
}
private setHiddenColumns(columns: DataColumn[]): DataColumn[] {
if (this.hiddenColumns) {
return columns.map(column => {
const columnShouldBeHidden = this.hiddenColumns.includes(column[this.hiddenColumnsKey]);
return {
...column,
isHidden: columnShouldBeHidden
};
});
}
return columns;
}
}

View File

@@ -34,6 +34,7 @@ export class ObjectDataColumn implements DataColumn {
sortingKey?: string;
header?: TemplateRef<any>;
draggable: boolean;
isHidden: boolean;
constructor(input: any) {
this.id = input.id ?? '';
@@ -50,5 +51,6 @@ export class ObjectDataColumn implements DataColumn {
this.sortingKey = input.sortingKey;
this.header = input.header;
this.draggable = input.draggable ?? false;
this.isHidden = input.isHidden ?? false;
}
}

View File

@@ -29,6 +29,7 @@ import { DataTableCellComponent } from './components/datatable-cell/datatable-ce
import { DataTableRowComponent } from './components/datatable-row/datatable-row.component';
import { DataTableComponent } from './components/datatable/datatable.component';
import { DateCellComponent } from './components/date-cell/date-cell.component';
import { ColumnsSelectorComponent } from './components/columns-selector/columns-selector.component';
import { EmptyListBodyDirective,
EmptyListComponent,
EmptyListFooterDirective,
@@ -42,12 +43,14 @@ import { HeaderFilterTemplateDirective } from './directives/header-filter-templa
import { CustomEmptyContentTemplateDirective } from './directives/custom-empty-content-template.directive';
import { CustomLoadingContentTemplateDirective } from './directives/custom-loading-template.directive';
import { CustomNoPermissionTemplateDirective } from './directives/custom-no-permission-template.directive';
import { MainMenuDataTableTemplateDirective } from './directives/main-data-table-action-template.directive';
import { JsonCellComponent } from './components/json-cell/json-cell.component';
import { ClipboardModule } from '../clipboard/clipboard.module';
import { DropZoneDirective } from './directives/drop-zone.directive';
import { DataColumnModule } from '../data-column/data-column.module';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { IconModule } from '../icon/icon.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
@@ -61,7 +64,9 @@ import { IconModule } from '../icon/icon.module';
DirectiveModule,
ClipboardModule,
DragDropModule,
IconModule
IconModule,
FormsModule,
ReactiveFormsModule
],
declarations: [
DataTableComponent,
@@ -75,6 +80,7 @@ import { IconModule } from '../icon/icon.module';
FileSizeCellComponent,
LocationCellComponent,
JsonCellComponent,
ColumnsSelectorComponent,
NoContentTemplateDirective,
NoPermissionTemplateDirective,
LoadingContentTemplateDirective,
@@ -82,6 +88,7 @@ import { IconModule } from '../icon/icon.module';
CustomEmptyContentTemplateDirective,
CustomLoadingContentTemplateDirective,
CustomNoPermissionTemplateDirective,
MainMenuDataTableTemplateDirective,
DropZoneDirective
],
exports: [
@@ -93,6 +100,7 @@ import { IconModule } from '../icon/icon.module';
DataTableCellComponent,
DataTableRowComponent,
DateCellComponent,
ColumnsSelectorComponent,
FileSizeCellComponent,
LocationCellComponent,
JsonCellComponent,
@@ -103,6 +111,7 @@ import { IconModule } from '../icon/icon.module';
CustomEmptyContentTemplateDirective,
CustomLoadingContentTemplateDirective,
CustomNoPermissionTemplateDirective,
MainMenuDataTableTemplateDirective,
DropZoneDirective
]
})

View File

@@ -0,0 +1,44 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { DataTableComponent } from '../components/datatable/datatable.component';
import { MainMenuDataTableTemplateDirective } from './main-data-table-action-template.directive';
describe('MainMenuDataTableTemplateDirective', () => {
let fixture: ComponentFixture<DataTableComponent>;
let dataTable: DataTableComponent;
let directive: MainMenuDataTableTemplateDirective;
beforeEach(() => {
fixture = TestBed.createComponent(DataTableComponent);
dataTable = fixture.componentInstance;
directive = new MainMenuDataTableTemplateDirective(dataTable);
});
afterEach(() => {
fixture.destroy();
});
it('applies template to the datatable', () => {
const template: any = 'test template';
directive.template = template;
directive.ngAfterContentInit();
expect(dataTable.mainActionTemplate).toBe(template);
});
});

View File

@@ -0,0 +1,36 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AfterContentInit, ContentChild, Directive, TemplateRef } from '@angular/core';
import { DataTableComponent } from '../components/datatable/datatable.component';
@Directive({
selector: 'adf-main-menu-datatable-template'
})
export class MainMenuDataTableTemplateDirective implements AfterContentInit {
@ContentChild(TemplateRef)
template: any;
constructor(private dataTable: DataTableComponent) {}
ngAfterContentInit() {
if (this.dataTable) {
this.dataTable.mainActionTemplate = this.template;
}
}
}

View File

@@ -38,6 +38,7 @@ export * from './components/empty-list/empty-list.component';
export * from './components/filesize-cell/filesize-cell.component';
export * from './components/json-cell/json-cell.component';
export * from './components/location-cell/location-cell.component';
export * from './components/columns-selector/columns-selector.component';
export * from './data/data-table.schema';
export * from './directives/loading-template.directive';