A modern, intuitive Angular filter builder component for creating complex boolean filter expressions. Outputs portable, Kendo-compatible CompositeFilterDescriptor JSON for seamless integration with MemberJunction views and grids.
npm install @memberjunction/ng-filter-builder
The Filter Builder provides a visual interface for constructing nested AND/OR filter expressions against entity fields. It supports multiple field types (string, number, boolean, date, lookup), nested groups up to a configurable depth, and generates a human-readable summary of the active filter.
graph TD
A["FilterBuilderComponent"] --> B["FilterGroupComponent"]
B --> C["FilterRuleComponent"]
B --> D["FilterRuleComponent"]
B --> E["Nested FilterGroupComponent"]
E --> F["FilterRuleComponent"]
A --> G["CompositeFilterDescriptor JSON"]
style A fill:#2d6a9f,stroke:#1a4971,color:#fff
style B fill:#7c5295,stroke:#563a6b,color:#fff
style C fill:#2d8659,stroke:#1a5c3a,color:#fff
style D fill:#2d8659,stroke:#1a5c3a,color:#fff
style E fill:#7c5295,stroke:#563a6b,color:#fff
style F fill:#2d8659,stroke:#1a5c3a,color:#fff
style G fill:#b8762f,stroke:#8a5722,color:#fff
import { FilterBuilderModule } from '@memberjunction/ng-filter-builder';
@NgModule({
imports: [FilterBuilderModule]
})
export class YourModule {}
<mj-filter-builder
[fields]="filterFields"
[filter]="currentFilter"
(filterChange)="onFilterChange($event)">
</mj-filter-builder>
Pass sources and the builder always writes SourceKey.FieldName. One source still prefixes. Several sources: two-pane field picker (source list | fields). Bare names in existing JSON still load.
<mj-filter-builder
[sources]="[
{ key: 'Order', label: 'Order', fields: orderFields },
{ key: 'BillToOrganization', label: 'Bill-to organization', fields: orgFields }
]"
[filter]="filter"
[showSummary]="true"
(filterChange)="onChange($event)">
</mj-filter-builder>
JSON: { "field": "BillToOrganization.Type", "operator": "eq", "value": "Member" }.
Evaluate and summarize without Angular:
import { CompositeFilter } from '@memberjunction/core';
const cf = CompositeFilter.FromDescriptor(filter);
cf.Evaluate({ BillToOrganization: org, Order: header });
cf.SummaryText({ SourceLabels: { BillToOrganization: 'Bill-to organization' } });
See Filter Builder & Evaluation.
import { FilterFieldInfo } from '@memberjunction/ng-filter-builder';
filterFields: FilterFieldInfo[] = [
{ name: 'Name', displayName: 'Name', type: 'string', description: 'Full display name of the contact' },
{ name: 'Age', displayName: 'Age', type: 'number', description: 'Age in years' },
{ name: 'IsActive', displayName: 'Active', type: 'boolean', description: 'Whether the record is currently active' },
{ name: 'CreatedAt', displayName: 'Created Date', type: 'date' },
{ name: 'CategoryID', displayName: 'Category', type: 'lookup', lookupEntityName: 'Categories' }
];
description & Viewport Flip-Up)FilterRuleComponent intentionally uses a purpose-built, fixed-positioned searchable field picker (role="listbox" / role="option") instead of a native <select> or single-line <mj-combobox>:
FilterFieldInfo.description is populated (for example from EntityField.Description), each option renders a secondary description line alongside the field's display name and data-type badge.sources has multiple entities, the dropdown renders a two-pane layout (entity source list on the left, searchable field list on the right).dropUp): Measures available viewport space below and above the trigger (accounting for transformed ancestor containers) and automatically opens upward when near the bottom of the screen.ArrowDown, ArrowUp, Enter, and Escape (closing only the open field menu via event.stopPropagation() + event.preventDefault() so parent modal dialogs remain open).<mj-filter-builder
[fields]="filterFields"
[config]="{
maxDepth: 3,
allowGroups: true,
showClearButton: true,
showApplyButton: false,
applyOnChange: true
}"
[showSummary]="true"
[disabled]="false"
(filterChange)="onFilterChange($event)"
(apply)="onApply($event)"
(clear)="onClear()">
</mj-filter-builder>
| Component | Selector | Purpose |
|---|---|---|
FilterBuilderComponent |
mj-filter-builder |
Top-level container with config, summary, and clear/apply buttons |
FilterGroupComponent |
internal | Renders a group of rules combined by AND/OR logic |
FilterRuleComponent |
internal | Renders a single filter rule (field, operator, value) |
| Type | Operators |
|---|---|
| String | contains, does not contain, equals, not equals, starts with, ends with, is empty, is not empty |
| Number | equals, not equals, greater than, greater/equal, less than, less/equal, is empty, is not empty |
| Boolean | is, is not, is empty, is not empty |
| Date | equals, not equals, is after, is on or after, is before, is on or before, is empty, is not empty |
| Lookup | equals, not equals, contains, does not contain, starts with, ends with, is empty, is not empty |
FilterOperator -- Union type of all operator stringsFilterLogic -- 'and' | 'or'FilterDescriptor -- Single filter conditionCompositeFilterDescriptor -- Group of filters with AND/OR logicFilterFieldInfo -- Field metadata for the builderFilterBuilderConfig -- Configuration optionsFilterValueOption -- Value option for dropdown fieldsCreateEmptyFilter() -- Creates a new empty CompositeFilterDescriptorCreateFilterRule(field, type) -- Creates a new filter rule with defaultsIsCompositeFilter(filter) -- Type guard for composite filtersIsSimpleFilter(filter) -- Type guard for simple filter descriptorsGetOperatorsForType(type) -- Returns available operators for a field typeOperatorRequiresValue(operator) -- Checks if an operator needs a value input
@memberjunction/ng-filter-builder
A modern, intuitive filter builder component for Angular applications. Creates complex boolean filter expressions with Kendo-compatible JSON output.