Skip to content

Commit

Permalink
Fixed #9547 - New FilterService API
Browse files Browse the repository at this point in the history
  • Loading branch information
cagataycivici committed Nov 20, 2020
1 parent 54e5323 commit 6e36f9e
Show file tree
Hide file tree
Showing 22 changed files with 466 additions and 481 deletions.
228 changes: 228 additions & 0 deletions src/app/components/api/filterservice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import { Injectable } from '@angular/core';
import { ObjectUtils } from '../utils/objectutils';

@Injectable({providedIn: 'root'})
export class FilterService {

filter(value: any[], fields: any[], filterValue: string, filterMatchMode: string, filterLocale?: string) {
let filteredItems: any[] = [];
let filterText = ObjectUtils.removeAccents(filterValue).toLocaleLowerCase(filterLocale);

if (value) {
for (let item of value) {
for (let field of fields) {
let fieldValue = ObjectUtils.removeAccents(String(ObjectUtils.resolveFieldData(item, field))).toLocaleLowerCase(filterLocale);

if (this.filters[filterMatchMode](fieldValue, filterText, filterLocale)) {
filteredItems.push(item);
break;
}
}
}
}

return filteredItems;
}

public filters = {
startsWith: (value, filter, filterLocale?):boolean => {
if (filter === undefined || filter === null || filter.trim() === '') {
return true;
}

if (value === undefined || value === null) {
return false;
}

let filterValue = ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale);
let stringValue = ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale);

return stringValue.slice(0, filterValue.length) === filterValue;
},

contains: (value, filter, filterLocale?):boolean => {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) {
return true;
}

if (value === undefined || value === null) {
return false;
}

let filterValue = ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale);
let stringValue = ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale);

return stringValue.indexOf(filterValue) !== -1;
},

notContains: (value, filter, filterLocale?):boolean => {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) {
return true;
}

if (value === undefined || value === null) {
return false;
}

let filterValue = ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale);
let stringValue = ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale);

return stringValue.indexOf(filterValue) === -1;
},

endsWith: (value, filter, filterLocale?):boolean => {
if (filter === undefined || filter === null || filter.trim() === '') {
return true;
}

if (value === undefined || value === null) {
return false;
}

let filterValue = ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale);
let stringValue = ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale);

return stringValue.indexOf(filterValue, stringValue.length - filterValue.length) !== -1;
},

equals: (value, filter, filterLocale?):boolean => {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) {
return true;
}

if (value === undefined || value === null) {
return false;
}

if (value.getTime && filter.getTime)
return value.getTime() === filter.getTime();
else
return ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale) == ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale);
},

notEquals: (value, filter, filterLocale?):boolean => {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) {
return false;
}

if (value === undefined || value === null) {
return true;
}

if (value.getTime && filter.getTime)
return value.getTime() !== filter.getTime();
else
return ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale) != ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale);
},

in: (value, filter: any[]):boolean => {
if (filter === undefined || filter === null || filter.length === 0) {
return true;
}

for (let i = 0; i < filter.length; i++) {
if (ObjectUtils.equals(value, filter[i])) {
return true;
}
}

return false;
},

between: (value, filter: any[]):boolean => {
if (filter == null || filter[0] == null || filter[0] == null) {
return true;
}

if (value === undefined || value === null) {
return false;
}

if (value.getTime)
return filter[0].getTime() >= value.getTime() && value.getTime() <= filter[1].getTime();
else
return filter[0] <= value && value <= filter[1];
},

lt: (value, filter, filterLocale?):boolean => {
if (filter === undefined || filter === null) {
return true;
}

if (value === undefined || value === null) {
return false;
}

if (value.getTime && filter.getTime)
return value.getTime() < filter.getTime();
else
return value < filter;
},

lte: (value, filter, filterLocale?):boolean => {
if (filter === undefined || filter === null) {
return true;
}

if (value === undefined || value === null) {
return false;
}

if (value.getTime && filter.getTime)
return value.getTime() <= filter.getTime();
else
return value <= filter;
},

gt: (value, filter, filterLocale?):boolean => {
if (filter === undefined || filter === null) {
return true;
}

if (value === undefined || value === null) {
return false;
}

if (value.getTime && filter.getTime)
return value.getTime() > filter.getTime();
else
return value > filter;
},

gte: (value, filter, filterLocale?):boolean => {
if (filter === undefined || filter === null) {
return true;
}

if (value === undefined || value === null) {
return false;
}

if (value.getTime && filter.getTime)
return value.getTime() >= filter.getTime();
else
return value >= filter;
},

is: (value, filter, filterLocale?):boolean => {
return this.filters.equals(value, filter, filterLocale);
},

isNot: (value, filter, filterLocale?): boolean => {
return this.filters.notEquals(value, filter, filterLocale);
},

before: (value, filter, filterLocale?): boolean => {
return this.filters.lt(value, filter, filterLocale);
},

after: (value, filter, filterLocale?): boolean => {
return this.filters.gt(value, filter, filterLocale);
}

}

register(rule: string, fn: Function) {
this.filters[rule] = fn;
}
}
1 change: 1 addition & 0 deletions src/app/components/api/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from './blockableui';
export * from './confirmation';
export * from './confirmationservice';
export * from './filtermetadata';
export * from './filterservice';
export * from './contextmenuservice';
export * from './lazyloadevent';
export * from './megamenuitem';
Expand Down
7 changes: 3 additions & 4 deletions src/app/components/dataview/dataview.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import {NgModule,Component,ElementRef,OnInit,AfterContentInit,Input,Output,EventEmitter,ContentChild,ContentChildren,QueryList,TemplateRef,OnChanges,SimpleChanges,ChangeDetectionStrategy,ChangeDetectorRef, ViewEncapsulation} from '@angular/core';
import {CommonModule} from '@angular/common';
import {ObjectUtils} from 'primeng/utils';
import {Header,Footer,PrimeTemplate,SharedModule} from 'primeng/api';
import {Header,Footer,PrimeTemplate,SharedModule,FilterService} from 'primeng/api';
import {PaginatorModule} from 'primeng/paginator';
import {BlockableUI} from 'primeng/api';
import {FilterUtils} from 'primeng/utils';

@Component({
selector: 'p-dataView',
Expand Down Expand Up @@ -143,7 +142,7 @@ export class DataView implements OnInit,AfterContentInit,BlockableUI,OnChanges {

initialized: boolean;

constructor(public el: ElementRef, public cd: ChangeDetectorRef) {}
constructor(public el: ElementRef, public cd: ChangeDetectorRef, public filterService: FilterService) {}

ngOnInit() {
if (this.lazy) {
Expand Down Expand Up @@ -306,7 +305,7 @@ export class DataView implements OnInit,AfterContentInit,BlockableUI,OnChanges {

if (this.value && this.value.length) {
let searchFields = this.filterBy.split(',');
this.filteredValue = FilterUtils.filter(this.value, searchFields, filter, filterMatchMode, this.filterLocale);
this.filteredValue = this.filterService.filter(this.value, searchFields, filter, filterMatchMode, this.filterLocale);

if (this.filteredValue.length === this.value.length ) {
this.filteredValue = null;
Expand Down
9 changes: 4 additions & 5 deletions src/app/components/dropdown/dropdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import {NgModule,Component,ElementRef,OnInit,AfterViewInit,AfterContentInit,Afte
import {trigger,style,transition,animate,AnimationEvent} from '@angular/animations';
import {CommonModule} from '@angular/common';
import {SelectItem} from 'primeng/api';
import {SharedModule,PrimeTemplate} from 'primeng/api';
import {SharedModule,PrimeTemplate, FilterService} from 'primeng/api';
import {DomHandler, ConnectedOverlayScrollHandler} from 'primeng/dom';
import {ObjectUtils} from 'primeng/utils';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms';
import {FilterUtils} from 'primeng/utils';
import {TooltipModule} from 'primeng/tooltip';
import {RippleModule} from 'primeng/ripple';

Expand Down Expand Up @@ -344,7 +343,7 @@ export class Dropdown implements OnInit,AfterViewInit,AfterContentInit,AfterView

preventModelTouched: boolean;

constructor(public el: ElementRef, public renderer: Renderer2, public cd: ChangeDetectorRef, public zone: NgZone) {}
constructor(public el: ElementRef, public renderer: Renderer2, public cd: ChangeDetectorRef, public zone: NgZone, public filterService: FilterService) {}

ngAfterContentInit() {
this.templates.forEach((item) => {
Expand Down Expand Up @@ -1051,7 +1050,7 @@ export class Dropdown implements OnInit,AfterViewInit,AfterContentInit,AfterView
if (this.group) {
let filteredGroups = [];
for (let optgroup of this.options) {
let filteredSubOptions = FilterUtils.filter(this.getOptionGroupChildren(optgroup), searchFields, this.filterValue, this.filterMatchMode, this.filterLocale);
let filteredSubOptions = this.filterService.filter(this.getOptionGroupChildren(optgroup), searchFields, this.filterValue, this.filterMatchMode, this.filterLocale);
if (filteredSubOptions && filteredSubOptions.length) {
filteredGroups.push({
label: optgroup.label,
Expand All @@ -1064,7 +1063,7 @@ export class Dropdown implements OnInit,AfterViewInit,AfterContentInit,AfterView
this.optionsToDisplay = filteredGroups;
}
else {
this.optionsToDisplay = FilterUtils.filter(this.options, searchFields, this.filterValue, this.filterMatchMode, this.filterLocale);
this.optionsToDisplay = this.filterService.filter(this.options, searchFields, this.filterValue, this.filterMatchMode, this.filterLocale);
}

this.optionsChanged = true;
Expand Down
7 changes: 3 additions & 4 deletions src/app/components/listbox/listbox.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { NgModule, Component, ElementRef, Input, Output, EventEmitter, AfterContentInit, ContentChildren, ContentChild, QueryList, TemplateRef,forwardRef, ChangeDetectorRef, ViewChild, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SharedModule, PrimeTemplate, Footer, Header } from 'primeng/api';
import { SharedModule, PrimeTemplate, Footer, Header, FilterService } from 'primeng/api';
import { DomHandler } from 'primeng/dom';
import { ObjectUtils } from 'primeng/utils';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { FilterUtils } from 'primeng/utils';
import { RippleModule } from 'primeng/ripple';

export const LISTBOX_VALUE_ACCESSOR: any = {
Expand Down Expand Up @@ -141,7 +140,7 @@ export class Listbox implements AfterContentInit, ControlValueAccessor {

public headerCheckboxFocus: boolean;

constructor(public el: ElementRef, public cd: ChangeDetectorRef) { }
constructor(public el: ElementRef, public cd: ChangeDetectorRef, public filterService: FilterService) { }

@Input() get options(): any[] {
return this._options;
Expand Down Expand Up @@ -426,7 +425,7 @@ export class Listbox implements AfterContentInit, ControlValueAccessor {

filterOptions() {
if (this.hasFilter() && this._options)
this._filteredOptions = this._options.filter(option => FilterUtils[this.filterMatchMode](this.getOptionLabel(option), this._filterValue, this.filterLocale));
this._filteredOptions = this._options.filter(option => this.filterService.filters[this.filterMatchMode](this.getOptionLabel(option), this._filterValue, this.filterLocale));
else
this._filteredOptions = null;
}
Expand Down
7 changes: 3 additions & 4 deletions src/app/components/multiselect/multiselect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import { trigger,style,transition,animate,AnimationEvent} from '@angular/animati
import { CommonModule } from '@angular/common';
import { DomHandler, ConnectedOverlayScrollHandler } from 'primeng/dom';
import { ObjectUtils } from 'primeng/utils';
import { SharedModule, PrimeTemplate, Footer, Header } from 'primeng/api';
import { SharedModule, PrimeTemplate, Footer, Header, FilterService } from 'primeng/api';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { ScrollingModule } from '@angular/cdk/scrolling';
import { FilterUtils } from 'primeng/utils';
import { TooltipModule } from 'primeng/tooltip';
import { RippleModule } from 'primeng/ripple';

Expand Down Expand Up @@ -361,7 +360,7 @@ export class MultiSelect implements OnInit,AfterViewInit,AfterContentInit,AfterV

preventModelTouched: boolean;

constructor(public el: ElementRef, public renderer: Renderer2, public cd: ChangeDetectorRef) {}
constructor(public el: ElementRef, public renderer: Renderer2, public cd: ChangeDetectorRef, public filterService: FilterService) {}

ngOnInit() {
this.updateLabel();
Expand Down Expand Up @@ -871,7 +870,7 @@ export class MultiSelect implements OnInit,AfterViewInit,AfterContentInit,AfterV
filterOptions() {
if (this.hasFilter() && this._options) {
let searchFields: string[] = (this.filterBy || this.optionLabel || 'label').split(',');
this._filteredOptions = FilterUtils.filter(this.options, searchFields, this._filterValue, this.filterMatchMode, this.filterLocale);
this._filteredOptions = this.filterService.filter(this.options, searchFields, this._filterValue, this.filterMatchMode, this.filterLocale);
}
else {
this._filteredOptions = null;
Expand Down
7 changes: 3 additions & 4 deletions src/app/components/orderlist/orderlist.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import {NgModule,Component,ElementRef,AfterViewChecked,AfterContentInit,Input,Output,ContentChildren,QueryList,TemplateRef,EventEmitter,ViewChild,ChangeDetectionStrategy, ViewEncapsulation, ChangeDetectorRef} from '@angular/core';
import {CommonModule} from '@angular/common';
import {ButtonModule} from 'primeng/button';
import {SharedModule,PrimeTemplate} from 'primeng/api';
import {SharedModule,PrimeTemplate,FilterService} from 'primeng/api';
import {DomHandler} from 'primeng/dom';
import {ObjectUtils} from 'primeng/utils';
import {FilterUtils} from 'primeng/utils';
import {RippleModule} from 'primeng/ripple';

@Component({
Expand Down Expand Up @@ -113,7 +112,7 @@ export class OrderList implements AfterViewChecked,AfterContentInit {

public _value: any[];

constructor(public el: ElementRef, public cd: ChangeDetectorRef) {}
constructor(public el: ElementRef, public cd: ChangeDetectorRef, public filterService: FilterService) {}

get selection(): any[] {
return this._selection;
Expand Down Expand Up @@ -212,7 +211,7 @@ export class OrderList implements AfterViewChecked,AfterContentInit {

filter() {
let searchFields: string[] = this.filterBy.split(',');
this.visibleOptions = FilterUtils.filter(this.value, searchFields, this.filterValue, this.filterMatchMode, this.filterLocale);
this.visibleOptions = this.filterService.filter(this.value, searchFields, this.filterValue, this.filterMatchMode, this.filterLocale);
}

isItemVisible(item: any): boolean {
Expand Down
Loading

0 comments on commit 6e36f9e

Please sign in to comment.