DevExtreme v26.1 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

Angular Filter Builder - With List

This demo shows how to filter data in the List using the FilterBuilder component. Note that the DataSource does not support the "between" operation. Call the getFilterExpression() method to convert it into DataSource-compatible operations.

Backend API
<div class="filter-container"> <dx-filter-builder [fields]="fields" [(value)]="filter" (onInitialized)="refreshDataSource()" > </dx-filter-builder> <dx-button text="Apply Filter" type="default" (onClick)="refreshDataSource()"> </dx-button> </div> <div class="list-container"> <dx-list [dataSource]="dataSource"> <div *dxTemplate="let item of 'item'"> <div class="product"> <img src="{{ item.ImageSrc }}" alt="Picture of {{ item.Name }}" /> <div>{{ item.Name }}</div> <div class="price">{{ item.Price | currency : "USD" : "symbol" : "1.0" }}</div> </div> </div> </dx-list> </div>
import { bootstrapApplication } from '@angular/platform-browser'; import { Component, ViewChild, enableProdMode, provideZoneChangeDetection } from '@angular/core'; import { CurrencyPipe } from '@angular/common'; import { DxListModule, DxButtonModule, DxTagBoxModule, DxFilterBuilderComponent, DxFilterBuilderModule, } from 'devextreme-angular'; import { DataSource } from 'devextreme-angular/common/data'; import { Fields, Filter, Service } from './app.service'; if (!/localhost/.test(document.location.host)) { enableProdMode(); } @Component({ selector: 'demo-app', providers: [Service], templateUrl: './app.component.html', styleUrls: ['./app.component.css'], imports: [ DxListModule, DxButtonModule, DxTagBoxModule, DxFilterBuilderModule, CurrencyPipe, ], }) export class AppComponent { @ViewChild(DxFilterBuilderComponent, { static: false }) filterBuilder: DxFilterBuilderComponent; dataSource: DataSource; fields: Fields; filter: Filter; constructor(service: Service) { this.fields = service.getFields(); this.filter = service.getFilter(); this.dataSource = new DataSource({ store: service.getProducts(), }); } refreshDataSource() { this.dataSource.filter(this.filterBuilder.instance.getFilterExpression()); this.dataSource.load(); } } bootstrapApplication(AppComponent, { providers: [ provideZoneChangeDetection({ eventCoalescing: true, runCoalescing: true }), ], });
::ng-deep .filter-container { background-color: transparent; box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.14), 0 0 2px 0 rgba(0, 0, 0, 0.12); border-radius: 6px; width: 45%; float: left; margin: 24px; height: 430px; } ::ng-deep .dx-filterbuilder { background-color: transparent; padding: 10px; height: 360px; margin: 5px; overflow: auto; } ::ng-deep .dx-filterbuilder .dx-texteditor { width: 135px; } ::ng-deep .dx-button { margin: 10px 20px; float: right; } ::ng-deep .list-container { float: right; width: 45%; } ::ng-deep .list-container .dx-scrollable-container { max-height: 430px; padding-left: 30px; } ::ng-deep .product { height: 65px; } ::ng-deep .product > img { height: 100%; float: left; } ::ng-deep .product > div { padding-left: 10px; vertical-align: top; line-height: 65px; font-size: 15px; float: left; } ::ng-deep .product > div.price { float: right; font-size: 18px; } ::ng-deep .dx-filterbuilder .dx-numberbox { width: 80px; }
import { Injectable } from '@angular/core'; export class Product { ID: number; Name: string; Price: number; Current_Inventory: number; Backorder: number; Manufacturing: number; Category: string; ImageSrc: string; } const filter = [ ['Category', '=', 'Video Players'], 'or', [ ['Category', '=', 'Monitors'], 'and', ['Price', 'between', [165, 700]], ], 'or', [ ['Category', '=', 'Televisions'], 'and', ['Price', 'between', [2000, 4000]], ], ]; const categories: string[] = [ 'Video Players', 'Televisions', 'Monitors', 'Projectors', 'Automation', ]; const fields = [ { dataField: 'ID', dataType: 'number', }, { dataField: 'Name', }, { dataField: 'Price', dataType: 'number', format: 'currency', }, { dataField: 'Current_Inventory', dataType: 'number', caption: 'Inventory', }, { dataField: 'Category', lookup: { dataSource: categories, }, }, ]; const products: Product[] = [{ ID: 1, Name: 'HD Video Player', Price: 330, Current_Inventory: 225, Backorder: 0, Manufacturing: 10, Category: 'Video Players', ImageSrc: '../../../../images/products/1.png', }, { ID: 3, Name: 'SuperPlasma 50', Price: 2400, Current_Inventory: 0, Backorder: 0, Manufacturing: 0, Category: 'Televisions', ImageSrc: '../../../../images/products/3.png', }, { ID: 4, Name: 'SuperLED 50', Price: 1600, Current_Inventory: 77, Backorder: 0, Manufacturing: 55, Category: 'Televisions', ImageSrc: '../../../../images/products/4.png', }, { ID: 5, Name: 'SuperLED 42', Price: 1450, Current_Inventory: 445, Backorder: 0, Manufacturing: 0, Category: 'Televisions', ImageSrc: '../../../../images/products/5.png', }, { ID: 6, Name: 'SuperLCD 55', Price: 1350, Current_Inventory: 345, Backorder: 0, Manufacturing: 5, Category: 'Televisions', ImageSrc: '../../../../images/products/6.png', }, { ID: 7, Name: 'SuperLCD 42', Price: 1200, Current_Inventory: 210, Backorder: 0, Manufacturing: 20, Category: 'Televisions', ImageSrc: '../../../../images/products/7.png', }, { ID: 8, Name: 'SuperPlasma 65', Price: 3500, Current_Inventory: 0, Backorder: 0, Manufacturing: 0, Category: 'Televisions', ImageSrc: '../../../../images/products/8.png', }, { ID: 9, Name: 'SuperLCD 70', Price: 4000, Current_Inventory: 95, Backorder: 0, Manufacturing: 5, Category: 'Televisions', ImageSrc: '../../../../images/products/9.png', }, { ID: 10, Name: 'DesktopLED 21', Price: 175, Current_Inventory: null, Backorder: 425, Manufacturing: 75, Category: 'Monitors', ImageSrc: '../../../../images/products/10.png', }, { ID: 12, Name: 'DesktopLCD 21', Price: 170, Current_Inventory: 210, Backorder: 0, Manufacturing: 60, Category: 'Monitors', ImageSrc: '../../../../images/products/12.png', }, { ID: 13, Name: 'DesktopLCD 19', Price: 160, Current_Inventory: 150, Backorder: 0, Manufacturing: 210, Category: 'Monitors', ImageSrc: '../../../../images/products/13.png', }, { ID: 14, Name: 'Projector Plus', Price: 550, Current_Inventory: null, Backorder: 55, Manufacturing: 10, Category: 'Projectors', ImageSrc: '../../../../images/products/14.png', }, { ID: 15, Name: 'Projector PlusHD', Price: 750, Current_Inventory: 110, Backorder: 0, Manufacturing: 90, Category: 'Projectors', ImageSrc: '../../../../images/products/15.png', }, { ID: 17, Name: 'ExcelRemote IR', Price: 150, Current_Inventory: 650, Backorder: 0, Manufacturing: 190, Category: 'Automation', ImageSrc: '../../../../images/products/17.png', }, { ID: 18, Name: 'ExcelRemote BT', Price: 180, Current_Inventory: 310, Backorder: 0, Manufacturing: 0, Category: 'Automation', ImageSrc: '../../../../images/products/18.png', }, { ID: 19, Name: 'ExcelRemote IP', Price: 200, Current_Inventory: 0, Backorder: 325, Manufacturing: 225, Category: 'Automation', ImageSrc: '../../../../images/products/19.png', }]; @Injectable() export class Service { getProducts(): Product[] { return products; } getFields(): any[] { return fields; } getCategories(): string[] { return categories; } getFilter(): any[] { return filter; } } export type Fields = typeof fields; export type Filter = typeof filter;
<!DOCTYPE html> <html lang="en"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/26.1.5/css/dx.light.css" /> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" /> </head> <body class="dx-viewport"> <div class="demo-container"> <demo-app>Loading...</demo-app> </div> <script src="https://cdn.jsdelivr.net/npm/zone.js@0.16.2/bundles/zone.umd.js"></script> <script src="./bundle.js" type="module"></script> </body> </html>