Skip to content

Commit

Permalink
feat(igx-combo): implement filtering with pipes, WIP, #1260
Browse files Browse the repository at this point in the history
  • Loading branch information
ViktorSlavov committed May 10, 2018
1 parent a6b54af commit 7133f3e
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 27 deletions.
17 changes: 17 additions & 0 deletions demos/app/combo/sample.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.small-red-circle {
background-color: #FF2344;
margin: 2% 5px 2% 0px;
width: 5px;
height: 5px;
border-radius: 50%;
vertical-align: middle;
display: inline-block;
}

.footer-class, .header-class {
color: #131313;
background-color: #d3d3d3;
cursor: not-allowed;
text-align: center;
font-weight: 400;
}
19 changes: 14 additions & 5 deletions demos/app/combo/sample.component.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
<ng-template #myCustomTemplate let-display let-key="primaryKey">
<div>I live in {{display[key]}}</div>
</ng-template>
<div class="sample-wrapper">
<page-header title="Combo" description="Combo lets you choose value from a list"></page-header>
<section class="sample-content">
<p>Change data to:</p>
<button class="igx-button" (click)="changeData('primitive')">Primitve</button>
<button class="igx-button" (click)="changeData('complex')">Complex</button>
<button class="igx-button" (click)="changeData()">Initial</button>
<igx-combo [data]="items" [filter]="true" [primaryKey]="'field'" [customTemplate]="myCustomTemplate"></igx-combo>
<igx-combo [placeholder]="'Location'" [data]="items" [filterable]="true" [primaryKey]="'field'" [width]="'400px'">
<ng-template #dropdownItemTemplate let-display let-key="primaryKey">
<div>
<span class="small-red-circle"></span>{{display[key]}}
</div>
</ng-template>
<ng-template #dropdownFooter>
<div class="footer-class">This is a footer</div>
</ng-template>
<ng-template #dropdownHeader>
<div class="header-class">This is a header</div>
</ng-template>
</igx-combo>
</section>
</div>
</div>
26 changes: 18 additions & 8 deletions src/combo/combo.component.html
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
<ng-template #complex let-display let-key="primaryKey">
{{display[key]}}
{{display[key]}}
</ng-template>
<ng-template #primitive let-display>
{{display}}
{{display}}
</ng-template>
<ng-template #empty>
<span>The list is empty</span>
</ng-template>

<div class="igx-combo">
<div class="igx-combo" [style.width]="width">
<!-- <button igxButton="raised" igxRipple (click)="toggleDropDown()">Toggle</button> -->
<igx-input-group>
<input (keyup)="hanldeKeyDown($event)" (focus)="toggleDropDown($event, true)" igxInput name="lastName" type="text" [(ngModel)]="value" />
<label igxLabel for="lastName">Last Name</label>
<input (keyup)="hanldeKeyDown($event)" (focus)="toggleDropDown($event, true)" igxInput name="comboInput" type="text" [(ngModel)]="value"
/>
<label igxLabel for="comboInput">{{placeholder}}</label>
</igx-input-group>
<igx-drop-down (onSelection)="onSelection($event)">
<igx-drop-down-item *ngFor="let item of displayedData">
<ng-container *ngTemplateOutlet="template; context: {$implicit: item, primaryKey: primaryKey};"></ng-container>
<igx-drop-down (onSelection)="onSelection($event)" [width]="width">
<ng-container *ngTemplateOutlet="dropdownHeader; context: {$impicit: this}">
</ng-container>
<igx-drop-down-item *ngIf="data.length === 0; else content" isDisabled={{true}}>
There are no items to be displayed.
</igx-drop-down-item>
<ng-template #content>
<igx-drop-down-item #content *ngFor="let item of data | comboFiltering:filteringExpressions:filteringLogic:caller:pipeTrigger">
<ng-container *ngTemplateOutlet="template; context: {$implicit: item, primaryKey: primaryKey};"></ng-container>
</igx-drop-down-item>
</ng-template>
<ng-container *ngTemplateOutlet="dropdownFooter; context: {$impicit: this}">
</ng-container>
</igx-drop-down>
<div class=""></div>
</div>
Expand Down
92 changes: 78 additions & 14 deletions src/combo/combo.component.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { CommonModule } from "@angular/common";
import {
ChangeDetectorRef, Component, ElementRef,
EventEmitter, Input, NgModule, OnDestroy, OnInit, Output, TemplateRef, ViewChild, HostListener
ChangeDetectorRef, Component, ContentChild,
ElementRef, EventEmitter, HostBinding, HostListener, Input, NgModule, OnDestroy, OnInit, Output, TemplateRef, ViewChild
} from "@angular/core";
import { FormsModule } from "@angular/forms";
import { IgxSelectionAPIService } from "../core/selection";
import { cloneArray } from "../core/utils";
import { STRING_FILTERS } from "../data-operations/filtering-condition";
import { FilteringLogic, IFilteringExpression } from "../data-operations/filtering-expression.interface";
import { IgxRippleModule } from "../directives/ripple/ripple.directive";
import { IgxDropDownItemComponent } from "../drop-down/drop-down-item.component";
import { IgxDropDownComponent, IgxDropDownModule } from "../drop-down/drop-down.component";
import { IgxInputGroupModule, IgxInputGroupComponent } from "../input-group/input-group.component";
import { IgxInputGroupComponent, IgxInputGroupModule } from "../input-group/input-group.component";
import { IgxComboFilterConditionPipe, IgxComboFilteringPipe} from "./combo.pipes";

export enum DataTypes {
EMPTY = "empty",
Expand All @@ -22,6 +26,9 @@ export enum DataTypes {
})
export class IgxComboComponent implements OnInit, OnDestroy {

protected _filteringLogic = FilteringLogic.And;
protected _pipeTrigger = 0;
protected _filteringExpressions = [];
private _dataType = "";
private _filteredData = [];
private _dropdownVisible = false;
Expand All @@ -42,17 +49,51 @@ export class IgxComboComponent implements OnInit, OnDestroy {
@ViewChild("empty", { read: TemplateRef })
protected emptyTemplate: TemplateRef<any>;

@ContentChild("dropdownHeader", { read: TemplateRef })
public dropdownHeader: TemplateRef<any>;

@ContentChild("dropdownFooter", { read: TemplateRef })
public dropdownFooter: TemplateRef<any>;

@ContentChild("dropdownItemTemplate", { read: TemplateRef })
public dropdownItemTemplate: TemplateRef<any>;

@Input()
public evalDisabled: (args) => boolean;

@Input()
public customTemplate: TemplateRef<any>;
public data;

@Input()
public data;
public filteringLogic = FilteringLogic.And;

@Input()
get filteringExpressions() {
return this._filteringExpressions;
}

set filteringExpressions(value) {
this._filteringExpressions = cloneArray(value);
this.cdr.markForCheck();
}

get caller() {
return this;
}

get pipeTrigger(): number {
return this._pipeTrigger;
}

@Input()
public filter;
public filterable;

@Input()
public placeholder;

@HostBinding("style.width")
@Input()
public width;

@Input()
public primaryKey;
Expand Down Expand Up @@ -86,20 +127,34 @@ export class IgxComboComponent implements OnInit, OnDestroy {

}

protected prepare_filtering_expression(state, searchVal, condition, ignoreCase) {
const newExpression = { searchVal, condition, ignoreCase };
state.push(newExpression);
}

public filter(term, condition, ignoreCase) {
const filteringState = this.filteringExpressions;
this.prepare_filtering_expression(filteringState, term, condition, ignoreCase);
this.filteringExpressions = filteringState;
}

public get displayedData() {
if (this.filter) {
return this._filteredData;
}
// if (this.filterable) {
// return this._filteredData;
// }
return this.data;
}
public hanldeKeyDown(evt) {
this._filteredData = this.data.filter((e) => this.getDataByType(e).indexOf(evt.target.value) > -1);
if (this.filterable) {
this.filter(evt.target.value, STRING_FILTERS.contains, true);
}
}

public onSelection(event) {
if (event.newSelection) {
if (event.newSelection !== event.oldSelection) {
this.value = this.getData();
this.inputGroup.isFilled = true;
}
}
}
Expand All @@ -108,11 +163,12 @@ export class IgxComboComponent implements OnInit, OnDestroy {
if (state !== undefined) {
if (state) {
this.dropDown.open();
this.inputGroup.isFilled = true;
}
}
}

private getDataType() {
public getDataType(): string {
if (!this.data || !this.data.length) {
return DataTypes.EMPTY;
}
Expand All @@ -127,8 +183,8 @@ export class IgxComboComponent implements OnInit, OnDestroy {
if (!this.displayedData || !this.displayedData.length) {
return this.emptyTemplate;
}
if (this.customTemplate) {
return this.customTemplate;
if (this.dropdownItemTemplate) {
return this.dropdownItemTemplate;
}
if (this._dataType === DataTypes.COMPLEX) {
return this.complexTemplate;
Expand All @@ -142,6 +198,14 @@ export class IgxComboComponent implements OnInit, OnDestroy {
};
}

public get filteredData(): any[] {
return this._filteredData;
}

public set filteredData(val: any[]) {
this._filteredData = val;
}

private getDataByType(dataObj) {
if (this._dataType === DataTypes.PRIMITIVE || this._dataType === DataTypes.EMPTY) {
return dataObj;
Expand Down Expand Up @@ -173,7 +237,7 @@ export interface IComboSelectionChangeEventArgs {
}

@NgModule({
declarations: [IgxComboComponent],
declarations: [IgxComboComponent, IgxComboFilterConditionPipe, IgxComboFilteringPipe],
exports: [IgxComboComponent],
imports: [IgxRippleModule, IgxDropDownModule, CommonModule, IgxInputGroupModule, FormsModule]
})
Expand Down
40 changes: 40 additions & 0 deletions src/combo/combo.pipes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Pipe, PipeTransform } from "@angular/core";
import { cloneArray } from "../core/utils";
import { DataUtil } from "../data-operations/data-util";
import { FilteringLogic, IFilteringExpression } from "../data-operations/filtering-expression.interface";
import { IgxComboComponent } from "../main";

@Pipe({
name: "comboFiltering",
pure: true
})
export class IgxComboFilteringPipe implements PipeTransform {

constructor() {}

public transform(collection: any[], expressions: IFilteringExpression | IFilteringExpression[],
logic: FilteringLogic, caller: IgxComboComponent, pipeTrigger: number) {
const state = { expressions: [], logic };
state.expressions = caller.filteringExpressions;

if (!state.expressions.length) {
return collection;
}

const result = DataUtil.filter(cloneArray(collection), state);
caller.filteredData = result;
return result;
}
}

@Pipe({
name: "filterCondition",
pure: true
})

export class IgxComboFilterConditionPipe implements PipeTransform {

public transform(value: string): string {
return value.split(/(?=[A-Z])/).join(" ");
}
}

0 comments on commit 7133f3e

Please sign in to comment.