{"id":2865,"date":"2025-07-13T06:35:39","date_gmt":"2025-07-13T06:35:39","guid":{"rendered":"https:\/\/www.infragistics.com\/blogs\/?p=2865"},"modified":"2025-07-16T08:05:41","modified_gmt":"2025-07-16T08:05:41","slug":"advanced-filtering-in-angular","status":"publish","type":"post","link":"https:\/\/www.infragistics.com\/blogs\/advanced-filtering-in-angular","title":{"rendered":"Mastering Advanced Filtering in Angular Grid Interfaces with Ignite UI\u00a0"},"content":{"rendered":"\n<p>Filtering is a core feature of any data grid, playing a critical role in helping users quickly and efficiently find and work with relevant data. As datasets grow in size and complexity, users need more than just simple text searches. This is where <a href=\"https:\/\/www.infragistics.com\/products\/ignite-ui-angular\" target=\"_blank\" rel=\"noreferrer noopener\">Ignite UI for Angular<\/a> and the <a href=\"https:\/\/www.infragistics.com\/products\/ignite-ui-angular\/angular\/components\/grid\/grid\" target=\"_blank\" rel=\"noreferrer noopener\">Grid component<\/a> come into play. It provides a robust filtering API that supports everything from basic operations to advanced, customizable logic, handling various filtering scenarios (such as advanced filtering, programmatic filtering, and others) with ease.&nbsp;<\/p>\n\n\n\n<p>Here\u2019s what this post will cover to help you understand how it all works and explore key advanced filtering techniques for complex Grid interfaces:&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Excel-style filtering&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Custom filtering operands&nbsp;&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Custom filtering strategies&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Advanced filtering&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Programmatic filtering&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Remote filtering&nbsp;<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"working-with-excel-style-filtering\">Working with Excel-Style Filtering&nbsp;<\/h2>\n\n\n\n<p>Excel-style filtering introduces familiar UI paradigms to Angular applications, enabling users to apply quick, column-based filters with ease.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What Are Some of the Most Common Use Cases?&nbsp;<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Quick filtering on a single column.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Multiple filter conditions per column.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Clear UI for non-technical users.&nbsp;<\/li>\n<\/ul>\n\n\n\n<p>This filtering mode is straightforward to implement and is useful in applications that require simple yet interactive filtering interfaces.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How to Enable Excel-Style Filtering?<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Set [allowFiltering] to true and [filterMode] to 'excelStyleFilter':\u00a0\n&lt;igx-grid [data]=\"data\"\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 [allowFiltering]=\"true\"\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 [filterMode]=\"'excelStyleFilter'\">\u00a0\n\u00a0 &lt;igx-column field=\"id\" header=\"ID\">&lt;\/igx-column>\u00a0\n\u00a0 &lt;!-- Additional columns -->\u00a0\n&lt;\/igx-grid><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"custom-filtering-operands\">Custom Filtering Operands<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/static.infragistics.com\/marketing\/Website\/blog\/angular-advanced-filtering\/adv-filtering-operand-animated.gif\" alt=\"advanced filtering\"\/><\/figure>\n\n\n\n<p>Built-in operands, such as Contains or Equals, cover common scenarios, but when your application requires domain-specific logic, custom operands provide the flexibility to extend the filtering framework.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What Are Some of the Most Common Use Cases?&nbsp;<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Enforce domain-specific filtering rules.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Implement flexible matching logic.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Support structured or non-standard data formats.&nbsp;<\/li>\n<\/ul>\n\n\n\n<p><strong>Example: Regex Match Operand<\/strong>&nbsp;<\/p>\n\n\n\n<p>This custom filtering operand enables users to apply regular expressions for filtering. For example, the regex ^\\s*\\S+\\s+\\S+\\s+\\S+\\s+\\S+\\s*$ filters product names containing exactly four words.&nbsp;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">export class ExtendedStringFilteringOperand extends IgxStringFilteringOperand {\u00a0\n\u00a0 constructor() {\u00a0\n\u00a0\u00a0\u00a0 super();\u00a0\n\u00a0\u00a0\u00a0 this.operations = [\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0 ...this.operations, \/\/ Keep default string operations\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 name: 'Regex Match',\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 iconName: 'search',\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 isUnary: false,\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 logic: (target: string, searchVal: string) => {\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try {\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 const regex = new RegExp(searchVal);\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return regex.test(target);\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } catch (e) {\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 console.error('Invalid regex pattern:', e);\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return false;\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0\n\u00a0\u00a0\u00a0 ];\u00a0\n\u00a0 }\u00a0\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Usage in Ignite UI for Angular Grid&nbsp;<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public extendedStringFilteringOperand = ExtendedStringFilteringOperand.instance(); \n&lt;igx-column field=\"productName\" \n            header=\"Product Name\" \n            dataType=\"string\" \n            [filters]=\"extendedStringFilteringOperand\"> \n&lt;\/igx-column><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Useful Custom Filtering Strategies to Try<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/download.infragistics.com\/marketing\/Website\/blog\/angular-advanced-filtering\/ignite-ui-filtering-animated.gif\" alt=\"ignite ui angular and advanced filtering\"\/><\/figure>\n\n\n\n<p>Basic filtering works well for straightforward scenarios. However, when your application needs to clean up input, support fuzzy logic, or apply different rules per column, a custom filtering strategy offers the flexibility you need.&nbsp;<\/p>\n\n\n\n<p>With a strategy in place, you control exactly how the grid evaluates each value against the filter conditions.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What Are Some of the Most Common Use Cases?&nbsp;<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The input or data must be transformed first, such as removing accents, extracting numbers, or simplifying text.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Matching involves tokens, partial phrases, or fuzzy logic that go beyond simple operands.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Different columns require unique filtering behaviors based on data type or business logic.&nbsp;<\/li>\n<\/ul>\n\n\n\n<p><strong>Example: Initials Matching Strategy<\/strong>&nbsp;<\/p>\n\n\n\n<p>This strategy filters data by transforming each value into its initials (e.g., &#8220;John Doe&#8221; \u2192 &#8220;jd&#8221;) and matching them against the filter condition.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">export class InitialsFilteringStrategy extends FilteringStrategy {\u00a0\n\u202f public override filter(data: [], expressionsTree: IFilteringExpressionsTree): any[] {\u00a0\n\u202f \u202f const result: any[] = [];\u00a0\n\u202f \u202f if (!expressionsTree || !expressionsTree.filteringOperands ||\u00a0\n\u202f \u202f \u202f \u202f expressionsTree.filteringOperands.length === 0 || !data.length) {\u00a0\n\u202f \u202f \u202f return data;\u00a0\n\u202f \u202f }\u00a0\n\u202f \u202f data.forEach((rec: any) => {\u00a0\n\u202f \u202f \u202f if (this.matchRecord(rec, expressionsTree)) {\u00a0\n\u202f \u202f \u202f \u202f result.push(rec);\u00a0\n\u202f \u202f \u202f }\u00a0\n\u202f \u202f });\u00a0\n\u202f \u202f return result;\u00a0\n\u202f }\u00a0\n\u202f public override findMatchByExpression(rec: any, expr: IFilteringExpression, isDate?: boolean, isTime?: boolean, grid?: GridType): boolean {\u00a0\n\u202f \u202f const initials = this.getFieldValue(rec, expr.fieldName, isDate, isTime, grid)\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .split(\/\\s+\/)\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .map(word => word[0]?.toLowerCase())\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .join('');\u00a0\n\u202f \u202f return expr.condition?.logic?.(initials, expr.searchVal, expr.ignoreCase) ?? false;\u00a0\n\u202f }\u00a0\n}<\/pre>\n\n\n\n<p>Note: To create a custom filtering strategy, you can either implement the IFilteringStrategy interface or extend the FilteringStrategy base class provided by the library.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"advanced-filtering\">Advanced Filtering&nbsp;&nbsp;<\/h2>\n\n\n\n<p>For complex data exploration needs, IgxGrid offers an Advanced Filtering UI. This feature allows users to build multi-condition queries across multiple columns using a dialog interface that supports nested logical expressions (AND, OR).&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What Are Some of the Most Common Use Cases?<strong>&nbsp;<\/strong>&nbsp;<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Apply filtering conditions across multiple columns to isolate precise data sets.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ideal for applications where non-technical users need to construct complex queries without code.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Handle advanced scenarios requiring nested AND \/ OR logic to define relationships between filters.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Seamlessly supports strings, numbers, dates, and custom types, making it suitable for diverse datasets.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Perfect for data-heavy UIs where deep filtering and user-friendly interfaces are both essential.&nbsp;<\/li>\n<\/ul>\n\n\n\n<p>This feature supports both internal and external filtering dialogs and seamlessly integrates with grid APIs, making it ideal for advanced Angular applications where filtering is not just a UI concern but a core part of the data access strategy&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How to Enable Advanced Filtering?&nbsp;<\/h3>\n\n\n\n<p>There are two options for getting started with Advanced Filtering.&nbsp;<\/p>\n\n\n\n<p><strong>Option 1: Internal Advanced Filtering<\/strong>&nbsp;<\/p>\n\n\n\n<p>Enable advanced filtering directly on the grid:&nbsp;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;igx-grid [data]=\"data\" [allowAdvancedFiltering]=\"true\">\u00a0\n\u00a0 &lt;igx-column field=\"id\" header=\"ID\">&lt;\/igx-column>\u00a0\n\u00a0 &lt;!-- Other columns -->\u00a0\n&lt;\/igx-grid><\/pre>\n\n\n\n<p>This adds an \u201cAdvanced Filtering\u201d option to the grid\u2019s UI menu.&nbsp;<\/p>\n\n\n\n<p><strong>Option 2: External Advanced Filtering Dialog<\/strong>&nbsp;<\/p>\n\n\n\n<p>You can also control the dialog externally using the igx-advanced-filtering-dialog component:&nbsp;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;igx-advanced-filtering-dialog [grid]=\"grid1\">&lt;\/igx-advanced-filtering-dialog>\u00a0\n&lt;igx-grid #grid1 [data]=\"data\">\u00a0\n\u00a0 &lt;igx-column field=\"id\" header=\"ID\">&lt;\/igx-column>\u00a0\n\u00a0 &lt;!-- Other columns -->\u00a0\n&lt;\/igx-grid><\/pre>\n\n\n\n<p>&nbsp;This setup gives you more control over when and how the dialog is shown.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Programmatically Building Advanced Filtering Expressions&nbsp;<\/h3>\n\n\n\n<p>In many applications, filtering isn\u2019t always triggered by direct user input. You might need to apply filters dynamically based on saved views, user roles, business logic, or external inputs.&nbsp;<\/p>\n\n\n\n<p>IgxGrid supports this with a flexible API that lets you create and apply filtering rules programmatically.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Core Concepts&nbsp;<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>FilteringExpression: Represents a single condition (e.g., status = &#8216;Active&#8217;)&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>FilteringExpressionsTree: Groups expressions using logical operators (AND, OR) to form complex queries&nbsp;<\/li>\n<\/ul>\n\n\n\n<p><strong>Example: Building a Filter Tree<\/strong>&nbsp;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public applyFiltering(department: string): void {\u00a0\n\u00a0 const today = new Date();\u00a0\n\u00a0 const threeYearsAgo = new Date(today.getFullYear() - 3, today.getMonth(), today.getDate());\u00a0\n\u00a0 const departmentAvgSalary = this.calculateAverageSalaryPerDepartment(department);\u00a0\n\u00a0 \/\/ Department filter: Department === specified value\u00a0\n\u00a0 const deptExpr: IFilteringExpression = {\u00a0\n\u00a0\u00a0\u00a0 fieldName: 'Department',\u00a0\n\u00a0\u00a0\u00a0 searchVal: department,\u00a0\n\u00a0\u00a0\u00a0 condition: IgxStringFilteringOperand.instance().condition('equals'),\u00a0\n\u00a0 };\u00a0\n\u00a0 \/\/ Tenure filter: HireDate before 3 years ago\u00a0\n\u00a0 const tenureExpr: IFilteringExpression = {\u00a0\n\u00a0\u00a0\u00a0 fieldName: 'HireDate',\u00a0\n\u00a0\u00a0\u00a0 searchVal: threeYearsAgo,\u00a0\n\u00a0\u00a0\u00a0 condition: IgxDateFilteringOperand.instance().condition('before'),\u00a0\n\u00a0 };\u00a0\n\u00a0 \/\/ Salary filter: GrossSalary within \u00b15% of department average\u00a0\n\u00a0 const salaryMinExpr: IFilteringExpression = {\u00a0\n\u00a0\u00a0\u00a0 fieldName: 'GrossSalary',\u00a0\n\u00a0\u00a0\u00a0 searchVal: departmentAvgSalary * 0.95,\u00a0\n\u00a0\u00a0\u00a0 condition: IgxNumberFilteringOperand.instance().condition('greaterThanOrEqualTo'),\u00a0\n\u00a0 };\u00a0\n\u00a0 const salaryMaxExpr: IFilteringExpression = {\u00a0\n\u00a0\u00a0\u00a0 fieldName: 'GrossSalary',\u00a0\n\u00a0\u00a0\u00a0 searchVal: departmentAvgSalary * 1.05,\u00a0\n\u00a0\u00a0\u00a0 condition: IgxNumberFilteringOperand.instance().condition('lessThanOrEqualTo'),\u00a0\n\u00a0 };\u00a0\n\u00a0 \/\/ Combine salary range conditions with OR\u00a0\n\u00a0 const salaryExprTree = new FilteringExpressionsTree(FilteringLogic.Or);\u00a0\n\u00a0 salaryExprTree.filteringOperands.push(salaryMinExpr, salaryMaxExpr);\u00a0\n\u00a0 \/\/ Build main AND tree with all filters\u00a0\n\u00a0 const mainExprTree = new FilteringExpressionsTree(FilteringLogic.And);\u00a0\n\u00a0 mainExprTree.filteringOperands.push(deptExpr, tenureExpr, salaryExprTree);\u00a0\n\u00a0 \/\/ Apply filters to the grid\u00a0\n\u00a0 this.treeGrid.advancedFilteringExpressionsTree = mainExprTree;\u00a0\n}<\/pre>\n\n\n\n<p>This example demonstrates how to programmatically build filters to show employees from the &#8216;Technology&#8217; department, hired at least 3 years ago, whose gross salaries are within \u00b15% of their department\u2019s average.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What Are Some of the Benefits?&nbsp;<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Full control over filtering behavior.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Easily integrate with user settings or saved filters.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Compatible with the advanced filtering UI (filters applied programmatically can be edited via UI).&nbsp;<\/li>\n<\/ul>\n\n\n\n<p>This approach is ideal when filters must be auto-applied based on context, or showing department-specific data to certain users, or pre-filtering based on a dashboard selection.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"remote-filtering\">Remote Filtering&nbsp;<\/h2>\n\n\n\n<p>When working with large datasets, client-side filtering may not be efficient or scalable. In such cases, IgxGrid supports remote filtering, where the filter expressions are constructed on the client and sent to the server for processing.&nbsp;<\/p>\n\n\n\n<p>This approach is ideal for virtualized grids, paged APIs, or scenarios where backend systems perform the heavy lifting.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What Are Some of the Most Common Use Cases?&nbsp;<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Virtualized grids with server-side paging.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Dashboards that require querying large datasets.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ensuring filters are enforced server-side for security or data privacy.&nbsp;<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">How Does It Work&nbsp;<\/h3>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Users interact with IgxGrid\u2019s filtering UI.&nbsp;<\/li>\n<\/ol>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>The grid builds a FilteringExpressionsTree representing active filters.&nbsp;<\/li>\n<\/ol>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>You serialize this filter tree and include it in API requests.&nbsp;<\/li>\n<\/ol>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li>Your server processes the filters and returns matching data.&nbsp;<\/li>\n<\/ol>\n\n\n\n<p><strong>Example: Generate Filter Query for Your API<\/strong>&nbsp;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">private buildFilterQuery(): string {\u00a0\n\u00a0 const expressionsTree = this.grid.filteringExpressionsTree;\u00a0\n\u00a0 if (!expressionsTree || expressionsTree.filteringOperands.length === 0) {\u00a0\n\u00a0\u00a0\u00a0 return '';\u00a0\n\u00a0 }\u00a0\n\u00a0 const filterParts: string[] = [];\u00a0\n\u00a0 expressionsTree.filteringOperands.forEach((expr: IFilteringExpression) => {\u00a0\n\u00a0\u00a0\u00a0 const field = expr.fieldName;\u00a0\n\u00a0\u00a0\u00a0 const condition = expr.condition.name;\u00a0\n\u00a0\u00a0\u00a0 const value = encodeURIComponent(expr.searchVal);\u00a0\n\u00a0\u00a0\u00a0 filterParts.push(`${field} ${condition} ${value}`);\u00a0\n\u00a0 });\u00a0\n\u00a0 return filterParts.join(' or ');\u00a0\n}\u00a0\nprivate buildDataUrl(): string {\u00a0\n\u00a0 const filterQuery = this.buildFilterQuery();\u00a0\n\u00a0 const baseUrl = 'https:\/\/myapi.example.com\/employees';\u00a0\n\u00a0 return filterQuery ? `${baseUrl}?$filter=${filterQuery}` : baseUrl;\u00a0\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Usage&nbsp;<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">const apiUrl = this.buildDataUrl();\u00a0\nthis.http.get(apiUrl).subscribe((data) => {\u00a0\n\u00a0 this.grid.data = data;\u00a0\n});\u00a0<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/Generated URL example\u00a0\nhttps:\/\/services.odata.org\/V4\/Northwind\/Northwind.svc\/Products?$filter=UnitPrice gt 50\u00a0and UnitsInStock gt 10<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"useful-backend-integration-tip\">Useful Backend Integration Tip<\/h2>\n\n\n\n<p>Ensure your server can interpret and apply the filter logic. Depending on your backend technology, you might:&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Map operators (e.g., contains, equals) to SQL or NoSQL equivalents.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Parse nested AND\/OR groups from the FilteringExpressionsTree.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Apply type-aware filtering (e.g., strings, numbers, dates).&nbsp;<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"wrap-up\">Wrap Up&nbsp;<\/h2>\n\n\n\n<p>To get the most out of IgxGrid\u2019s filtering capabilities, explore the Ignite UI for Angular documentation, check out our <a href=\"https:\/\/www.infragistics.com\/products\/ignite-ui-angular\/grid-samples\" target=\"_blank\" rel=\"noreferrer noopener\">Grid Samples<\/a> to see filtering features in action, and feel free to experiment with combining formatted filtering and custom operands for a highly tailored UX.&nbsp;<\/p>\n\n\n\n<p>With these tools, you can build enterprise-grade data experiences that empower users to explore, analyze, and act on their data more efficiently and with greater insight.&nbsp;<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Do you know how to enable Excel-style filtering, Custom filtering operands, Custom filtering strategies, Advanced filtering, Programmatic filtering, or Remote filtering? This article will show you how, including code snippets, examples, and use cases.<\/p>\n","protected":false},"author":171,"featured_media":2869,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,17],"tags":[53,23,48,38],"class_list":["post-2865","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-angular","category-how-to","tag-advanced-filtering","tag-angular","tag-angular-grids","tag-ignite-ui-angular"],"_links":{"self":[{"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/posts\/2865","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/users\/171"}],"replies":[{"embeddable":true,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/comments?post=2865"}],"version-history":[{"count":18,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/posts\/2865\/revisions"}],"predecessor-version":[{"id":2907,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/posts\/2865\/revisions\/2907"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/media\/2869"}],"wp:attachment":[{"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/media?parent=2865"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/categories?post=2865"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.infragistics.com\/blogs\/wp-json\/wp\/v2\/tags?post=2865"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}