packages/ui/src/lib/list/list-header/list-header.component.ts
This component renders, as the name states, the header of a list.
changeDetection | ChangeDetectionStrategy.OnPush |
selector | ec-list-header |
templateUrl | ./list-header.component.html |
Properties |
|
Methods |
Inputs |
constructor(listConfig: ListConfigService, cdr: ChangeDetectorRef)
|
|||||||||
Parameters :
|
list | |
Type : List<any>
|
|
The list instance |
selection | |
Type : Selection<any>
|
|
The selection instance. This is optional. If It is not provided, no checkbox will be visible. |
clearFilter |
clearFilter()
|
Returns :
void
|
Public filterField | ||||
filterField(property)
|
||||
opens the given filter pop and closes all others
Parameters :
Returns :
void
|
initFilterForm | ||||
initFilterForm(filterForm)
|
||||
Parameters :
Returns :
void
|
inputReady | ||||
inputReady(input)
|
||||
Parameters :
Returns :
void
|
isLastColumn | ||||||
isLastColumn(field: Field)
|
||||||
Yields true if the given field is the last column of the current list header
Parameters :
Returns :
boolean
|
ngOnChanges | ||||
ngOnChanges(changes?)
|
||||
Parameters :
Returns :
void
|
resetFilter |
resetFilter()
|
Returns :
void
|
setFilter | ||||||
setFilter(field, value)
|
||||||
Parameters :
Returns :
void
|
toggledFilterPop | ||||
toggledFilterPop(active)
|
||||
Parameters :
Returns :
void
|
Public toggleVisibility | ||||||
toggleVisibility(field: Field)
|
||||||
Toggles the fields visibility in the list
Parameters :
Returns :
void
|
Public cdr |
Type : ChangeDetectorRef
|
filteredField |
Type : any
|
filterForm |
Type : FormComponent<any>
|
filterFormConfig |
Type : ListConfig<any>
|
The config for the filter form |
filterInput |
Type : InputComponent
|
filterPop |
Type : PopComponent
|
Decorators :
@ViewChild('filterPop', {static: true})
|
The pop dropdowns that contain the filtering |
Public listConfig |
Type : ListConfigService
|
This document conceptualizes the ec-list-header.
The list-header displays the field labels in columns. If a fields are sortable or filterable, a clickeable icons will be shown.
If a field has the option "filterable" set to true, a search icon will be shown. When clicking the icon, an input field will appear above the list header which can be used to filter the list by the field property.
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, ViewChild } from '@angular/core';
import { Field, List, ListConfig, Selection } from '@ec.components/core';
import { FormComponent } from '../../form/form.component';
import { PopComponent } from '../../pop/pop.component';
import { ListConfigService } from '../list-config.service';
import { InputComponent } from '../../io/input/input.component';
/** This component renders, as the name states, the header of a list.*/
@Component({
selector: 'ec-list-header',
templateUrl: './list-header.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ListHeaderComponent implements OnChanges {
/** The list instance */
@Input() list: List<any>;
/** The selection instance. This is optional. If It is not provided, no checkbox will be visible.*/
@Input() selection: Selection<any>;
/** The pop dropdowns that contain the filtering */
@ViewChild('filterPop', { static: true }) filterPop: PopComponent;
/** The config for the filter form */
filterFormConfig: ListConfig<any>;
filteredField: any;
filterForm: FormComponent<any>;
filterInput: InputComponent;
constructor(public listConfig: ListConfigService, public cdr: ChangeDetectorRef) {}
setFilter(field, value) {
this.list.setFilter({ [field.property]: value });
}
inputReady(input) {
this.filterInput = input;
input.focus(true);
}
initFilterForm(filterForm) {
// is called when form is ready
this.filterForm = filterForm;
if (this.list.config.defaultFilter) {
this.filterField(this.list.config.defaultFilter);
}
}
ngOnChanges(changes?) {
if (!changes.list) {
return;
}
if (!this.list || !this.list.config || !this.list.config.fields) {
return;
}
/* this.list.change$.subscribe(() => {
if (this.filterInput) {
// this.filterInput.focus(true);
}
}); */
this.filterFormConfig = {
...this.list.config,
fields: this.list.filterableFields().reduce((fields, field) => {
return {
...fields,
[field.property]: {
...this.list.config.fields[field.property],
view: field.getView('filter'),
required: false,
readOnly: false,
immutable: false,
disabled: false,
create: true,
form: true,
autofocus: true,
nestedCrudConfig: {
...field.nestedCrudConfig,
methods: ['get'],
},
},
};
}, {}),
};
}
/** opens the given filter pop and closes all others */
public filterField(property) {
if (this.filteredField) {
if (this.filteredField.property === property) {
/* this.filterPop.hide(); */
if (this.filterInput) {
this.filterInput.focus(true);
}
return;
}
this.clearFilter();
}
// patch current filter value to control
const control = this.filterForm.group.get(property);
if (!control) {
console.warn('no control found for ' + property + '. Is it filterable?', this.list.config, this.filterForm.group);
return;
}
this.filterForm.group.get(property).patchValue(this.list.getFilterValue(property));
this.filteredField = this.filterForm.form.getField(property);
setTimeout(() => this.filterPop.show());
}
resetFilter() {
if (!this.filteredField || !this.list || !this.list.isFiltered(this.filteredField.property)) {
return;
}
this.filterForm.group.get(this.filteredField.property).reset();
this.list.clearFilter();
}
clearFilter() {
if (!this.filteredField || !this.list.isFiltered(this.filteredField.property)) {
delete this.filteredField;
return;
}
this.resetFilter();
delete this.filteredField;
}
toggledFilterPop(active) {
if (!active) {
this.clearFilter();
}
if (this.filterInput) {
this.filterInput.focus(true);
}
}
/** Toggles the fields visibility in the list */
public toggleVisibility(field: Field) {
this.list.toggleVisibility(field);
this.listConfig.storeConfig(this.list);
}
/** Yields true if the given field is the last column of the current list header */
isLastColumn(field: Field) {
if (!this.list || !this.list.fields) {
return;
}
const visibleColumns = this.list.fields.filter((f) => !f.hideInList);
return field.property === visibleColumns[visibleColumns.length - 1].property;
}
}
<ec-pop (toggle)="toggledFilterPop($event)" [hideOnEscape]="false" #filterPop>
<div class="ec-searchbar">
<div *ngIf="filteredField" data-grid="no-gutter">
<div data-col="auto">
<div class="input-group">
<div class="input-group__addon" data-flex="center">
<ec-icon name="search"></ec-icon>
</div>
<ec-input
(ready)="inputReady($event)"
(changed)="setFilter(filteredField, $event)"
[lazy]="true"
[component]="filteredField.getComponent('filter') || filteredField.input"
[field]="filteredField"
[group]="filterForm?.group"
[debounce]="200"
*ngIf="filterPop.active && filterForm?.group"
#filterInput
data-col="auto"
></ec-input>
<div
class="input-group__addon"
*ngIf="list?.isFiltered(filteredField.property)"
data-flex="center center-items"
>
<a class="btn btn_clear btn_square btn_small is-ink-light" (click)="resetFilter()">
<ec-icon name="clear"></ec-icon>
</a>
</div>
</div>
</div>
<div data-col="fit">
<div tabindex="0" class="dropdown dropdown_right">
<span class="btn btn_clear btn_square">
<ec-icon name="filter"></ec-icon>
</span>
<div class="dropdown-options">
<div *ngFor="let field of list?.sortableFields()">
<a
class="dropdown-option sorting-option"
[class.is-sorted-desc]="list.isSorted(field.property, true)"
[class.is-sorted-asc]="list.isSorted(field.property, false)"
>
<span class="sorting-option-indicator">
<span class="asc" (click)="list.toggleSort(field.property, false)"></span>
<span class="desc" (click)="list.toggleSort(field.property, true)"></span>
</span>
<span (click)="list.toggleSort(field.property)">{{ field.getLabel() }}</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</ec-pop>
<div *ngIf="filterFormConfig">
<ec-form
[config]="filterFormConfig"
[value]="list?.config?.filter"
[empty]="true"
#filterForm
(ready)="initFilterForm($event)"
[lazy]="true"
></ec-form>
<div class="ec-list-header">
<div class="ec-list-cell ec-list-item__selector" *ngIf="list?.config?.selectMode && !list?.isEmpty()">
<input
type="checkbox"
(click)="selection?.toggleAll(list?.page)"
[checked]="selection?.hasAll(list?.page)"
[disabled]="selection?.config?.solo"
/>
</div>
<div
class="ec-list-cell"
*ngFor="let field of list?.fields; let i = index"
[ngClass]="'ec-list-cell_' + field.getView('output') + ' ' + (field?.classes || '')"
[class.is-hidden]="field.hideInList"
[class.is-sortable]="field.sortable"
[class.is-sorted]="list.isSorted(field.property)"
[class.is-filterable]="field.filterable"
[class.is-filtered]="list.isFiltered(field.property)"
[class.is-last-column]="isLastColumn(field)"
[class.is-sorted-desc]="list.isSorted(field.property, true)"
[class.is-sorted-asc]="list.isSorted(field.property, false)"
>
<!-- [class.is-filter-active]="filterPop.active"-->
<a (click)="filterField(field.property)" class="is-filterable-control" *ngIf="field.filterable">
<ec-icon name="search"></ec-icon>
</a>
<!-- <a (click)="toggleVisibility(field)" class="is-visibility-control">
<ec-icon name="eye-closed"></ec-icon>
</a> -->
<span
class="ec-list-column-title"
(click)="field.sortable && list.toggleSort(field.property)"
[title]="field.property"
>
{{ field.getLabel() }}
</span>
<span class="is-sortable-indicator" *ngIf="field.sortable">
<span class="asc" (click)="list.toggleSort(field.property, false)"></span>
<span class="desc" (click)="list.toggleSort(field.property, true)"></span>
</span>
</div>
<div class="dropdown dropdown_right ec-list-column-filter" tabindex="0" *ngIf="!list?.config?.disableColumnFilter">
<span>☰</span>
<div class="dropdown-options">
<div
class="dropdown-option"
*ngFor="let field of list?.fields"
(click)="toggleVisibility(field)"
[class.is-active]="!field.hideInList"
[class.is-hidden]="field.hideInColumnFilter"
>
{{ field.getLabel() }}
</div>
</div>
</div>
</div>
</div>