Filter Pipe updated,

FuseUtils added,
Filtering applied for mail, todo, chat app.
This commit is contained in:
mustafahlvc 2017-07-28 11:29:29 +03:00
parent 0b3a7ef919
commit 2d459864f1
8 changed files with 159 additions and 160 deletions

82
src/app/core/fuseUtils.ts Normal file
View File

@ -0,0 +1,82 @@
export class FuseUtils
{
public static filterArrayByString(mainArr, searchText)
{
searchText = searchText.toLowerCase();
return mainArr.filter(itemObj => {
return this.searchInObj(itemObj, searchText);
});
}
public static searchInObj(itemObj, searchText)
{
for ( const prop in itemObj )
{
if ( !itemObj.hasOwnProperty(prop) )
{
continue;
}
const value = itemObj[prop];
if ( typeof value === 'string' )
{
if ( this.searchInSting(value, searchText) )
{
return true;
}
}
else if ( Array.isArray(value) )
{
if ( this.searchInArray(value, searchText) )
{
return true;
}
}
if ( typeof value === 'object' )
{
if ( this.searchInObj(value, searchText) )
{
return true;
}
}
}
}
public static searchInArray(arr, searchText)
{
for ( const value of arr )
{
if ( typeof value === 'string' )
{
if ( this.searchInSting(value, searchText) )
{
return true;
}
}
if ( typeof value === 'object' )
{
if ( this.searchInObj(value, searchText) )
{
return true;
}
}
}
}
public static searchInSting(value, searchText)
{
if ( value.toLowerCase().includes(searchText) )
{
return true;
}
return false;
}
}

View File

@ -1,152 +1,11 @@
/**
* Created by vadimdez on 28/06/16.
*/
import { Pipe, Injectable } from '@angular/core';
import { Pipe, PipeTransform } from '@angular/core';
import { FuseUtils } from '../fuseUtils';
@Pipe({
name: 'filterBy',
pure: false
})
@Injectable()
export class FilterPipe {
private filterByString(filter) {
if (filter) {
filter = filter.toLowerCase();
}
return value => {
return !filter || (value ? ('' + value).toLowerCase().indexOf(filter) !== -1 : false);
}
}
private filterByBoolean(filter) {
return value => {
return Boolean(value) === filter;
}
}
private filterByObject(filter) {
return value => {
for (let key in filter) {
if (key === '$or') {
if (!this.filterByOr(filter.$or)(this.getValue(value))) {
return false;
}
continue;
}
if (!value.hasOwnProperty(key) && !Object.getOwnPropertyDescriptor(Object.getPrototypeOf(value), key)) {
return false;
}
let val = this.getValue(value[key]);
const filterType = typeof filter[key];
let isMatching;
if (filterType === 'boolean') {
isMatching = this.filterByBoolean(filter[key])(val);
} else if (filterType === 'string') {
isMatching = this.filterByString(filter[key])(val);
} else if (filterType === 'object') {
isMatching = this.filterByObject(filter[key])(val);
} else {
isMatching = this.filterDefault(filter[key])(val);
}
if (!isMatching) {
return false;
}
}
return true;
}
}
/**
* Filter value by $or
*
* @param filter
* @returns {(value:any)=>boolean}
*/
private filterByOr(filter: any[]) {
return (value: any) => {
let hasMatch = false;
const length = filter.length;
const isArray = value instanceof Array;
const arrayComparison = (i) => {
return value.indexOf(filter[i]) !== -1;
};
const otherComparison = (i) => {
return value === filter[i];
};
const comparison = isArray ? arrayComparison : otherComparison;
for (let i = 0; i < length; i++) {
if (comparison(i)) {
hasMatch = true;
break;
}
}
return hasMatch;
};
}
/**
* Checks function's value if type is function otherwise same value
* @param value
* @returns {any}
*/
private getValue(value: any) {
return typeof value === 'function' ? value() : value;
}
/**
* Defatul filterDefault function
*
* @param filter
* @returns {(value:any)=>boolean}
*/
private filterDefault(filter) {
return value => {
return filter === undefined || filter == value;
}
}
private isNumber(value) {
return !isNaN(parseInt(value, 10)) && isFinite(value);
}
transform(array: any[], filter: any): any {
const type = typeof filter;
if (!array) {
return array;
}
if (type === 'boolean') {
return array.filter(this.filterByBoolean(filter));
}
if (type === 'string') {
if (this.isNumber(filter)) {
return array.filter(this.filterDefault(filter));
}
return array.filter(this.filterByString(filter));
}
if (type === 'object') {
return array.filter(this.filterByObject(filter));
}
if (type === 'function') {
return array.filter(filter);
}
return array.filter(this.filterDefault(filter));
@Pipe({name: 'filter'})
export class FilterPipe implements PipeTransform
{
transform(mainArr: any[], searchText: string, property: string): any
{
return FuseUtils.filterArrayByString(mainArr, searchText);
}
}

View File

@ -82,7 +82,7 @@
<md-icon>search</md-icon>
<input [(ngModel)]="chatSearch.name" type="text" placeholder="Search or start new chat" fxFlex>
<input [(ngModel)]="searchText" type="text" placeholder="Search or start new chat" fxFlex>
</div>
</div>
@ -106,12 +106,12 @@
<!-- CHATS LIST-->
<div class="chat-list" fxLayout="column">
<div md-subheader *ngIf="(user.chatList | filterBy: chatSearch).length > 0">
<div md-subheader *ngIf="(user.chatList | filter: searchText).length > 0">
Chats
</div>
<button md-button class="contact"
*ngFor="let chat of user.chatList | filterBy: chatSearch"
*ngFor="let chat of user.chatList | filter: searchText"
(click)="getChat(chat.contactId)" ngClass="{'unread':contact.unread}">
<div fxLayout="row" fxLayoutAlign="start center">
@ -146,13 +146,13 @@
<!-- CONTACTS LIST-->
<div class="contact-list" fxLayout="column">
<div md-subheader *ngIf="(contacts| filterBy: chatSearch).length > 0">
<div md-subheader *ngIf="(contacts| filter: searchText).length > 0">
Contacts
</div>
<button md-button class="contact"
ng-show="chatSearch"
*ngFor="let contact of contacts| filterBy: chatSearch"
*ngFor="let contact of contacts| filter: searchText"
(click)="getChat(contact.id)">
<div fxLayout="row" fxLayoutAlign="start center">
@ -171,7 +171,7 @@
<!-- / CONTACTS LIST-->
<!-- NO RESULTS MESSAGE -->
<div *ngIf="(contacts| filterBy: chatSearch).length === 0" class="no-results-message">
<div *ngIf="(contacts| filter: searchText).length === 0" class="no-results-message">
No results..
</div>
<!-- NO RESULTS MESSAGE-->

View File

@ -14,6 +14,7 @@ export class ChatsSidenavComponent implements OnInit
chats: any[];
contacts: any[];
chatSearch: any;
searchText = '';
constructor(private chatService: ChatService,
private fuseMdSidenavService: FuseMdSidenavHelperService,

View File

@ -29,7 +29,7 @@
<div class="search" flex fxLayout="row" fxLayoutAlign="start center">
<md-icon>search</md-icon>
<input fxFlex type="text" placeholder="Search for an e-mail or contact">
<input [formControl]="searchInput" placeholder="Search for an e-mail or contact" fxFlex>
</div>
</div>

View File

@ -1,6 +1,8 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { MailService } from './mail.service';
import { Subscription } from 'rxjs/Subscription';
import { FormControl } from '@angular/forms';
import { FuseUtils } from '../../../core/fuseUtils';
@Component({
selector : 'fuse-mail',
@ -14,20 +16,30 @@ export class MailComponent implements OnInit, OnDestroy
folders: any[];
filters: any[];
labels: any[];
mails: any[];
searchInput: FormControl;
onSelectedMailsChanged: Subscription;
onFoldersChanged: Subscription;
onFiltersChanged: Subscription;
onLabelsChanged: Subscription;
onMailsChanged: Subscription;
constructor(
private mailService: MailService
)
constructor(private mailService: MailService)
{
this.searchInput = new FormControl('');
}
ngOnInit()
{
// Subscribe to update mails on changes
this.onMailsChanged =
this.mailService.onMailsChanged
.subscribe(mails => {
this.mails = mails;
});
this.onSelectedMailsChanged =
this.mailService.onSelectedMailsChanged
.subscribe(selectedMails => {
@ -55,6 +67,22 @@ export class MailComponent implements OnInit, OnDestroy
.subscribe(labels => {
this.labels = this.mailService.labels;
});
this.searchInput.valueChanges
.debounceTime(300)
.distinctUntilChanged()
.subscribe(searchText => {
if ( searchText !== '' )
{
const newArr = FuseUtils.filterArrayByString(this.mails, searchText);
this.mailService.onMailsChanged.next(newArr);
}
else
{
this.mailService.getMails();
}
});
}
ngOnDestroy()

View File

@ -29,7 +29,7 @@
<div class="search" flex fxLayout="row" fxLayoutAlign="start center">
<md-icon>search</md-icon>
<input fxFlex type="text" placeholder="Search for an todo">
<input [formControl]="searchInput" placeholder="Search for an todo" fxFlex>
</div>
</div>

View File

@ -1,6 +1,9 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
import { TodoService } from './todo.service';
import { FormControl } from '@angular/forms';
import { Todo } from './todo.model';
import { FuseUtils } from '../../../core/fuseUtils';
@Component({
selector : 'fuse-todo',
@ -11,19 +14,30 @@ export class TodoComponent implements OnInit, OnDestroy
{
hasSelectedTodos: boolean;
isIndeterminate: boolean;
todos: Todo[];
filters: any[];
tags: any[];
searchInput: FormControl;
onTodosChanged: Subscription;
onSelectedTodosChanged: Subscription;
onFiltersChanged: Subscription;
onTagsChanged: Subscription;
constructor(private todoService: TodoService)
{
this.searchInput = new FormControl('');
}
ngOnInit()
{
// Subscribe to update todos on changes
this.onTodosChanged =
this.todoService.onTodosChanged
.subscribe(todos => {
this.todos = todos;
});
this.onSelectedTodosChanged =
this.todoService.onSelectedTodosChanged
.subscribe(selectedTodos => {
@ -45,6 +59,21 @@ export class TodoComponent implements OnInit, OnDestroy
.subscribe(tags => {
this.tags = this.todoService.tags;
});
this.searchInput.valueChanges
.debounceTime(300)
.distinctUntilChanged()
.subscribe(searchText => {
if ( searchText !== '' )
{
const newArr = FuseUtils.filterArrayByString(this.todos, searchText);
this.todoService.onTodosChanged.next(newArr);
}
else
{
this.todoService.getTodos();
}
});
}
ngOnDestroy()