Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Query Builder topic #6046

Merged
merged 21 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
43a6b17
docs(query-builder): update topic with nested queries and templating
igdmdimitrov Sep 27, 2024
33c0759
chore(*): address PR comments
igdmdimitrov Sep 27, 2024
fae918e
Update en/components/query-builder.md
igdmdimitrov Oct 1, 2024
aa71cc1
docs(query-builder): update template snippet and add sample
igdmdimitrov Oct 3, 2024
b30707e
docs(query-builder): add supporting text for example
igdmdimitrov Oct 4, 2024
8f85db2
docs(query-builder): remove selection and add some changes after re-d…
teodosiah Feb 10, 2025
0594dcf
Update en/components/query-builder.md
teodosiah Feb 10, 2025
c3118bf
docs(query-builder): add formatter section
teodosiah Feb 10, 2025
4b90062
Merge branch 'thristodorova/update-query-builder-topic' of https://gi…
teodosiah Feb 10, 2025
38efbfc
Merge branch 'vnext' into thristodorova/update-query-builder-topic
teodosiah Feb 10, 2025
9fb7972
Merge branch 'thristodorova/update-query-builder-topic' of https://gi…
teodosiah Feb 11, 2025
9bff84e
Merge branch 'thristodorova/update-query-builder-topic' of https://gi…
teodosiah Feb 11, 2025
f265b59
docs(query-builder): add keyboard interaction and dragging sections
teodosiah Feb 11, 2025
de98495
docs(query-builder): add drag and drop section
ivanvpetrov Feb 13, 2025
59477ce
docs(query-builder): fix formatter code-snippet
teodosiah Feb 14, 2025
77985cd
docs(query-builder): add example gifs
ivanvpetrov Feb 14, 2025
605b5c7
docs(query-builder): reworked drag and drop
ivanvpetrov Feb 14, 2025
df9bcdb
docs(query-builder): improved keyboard interaction text
ivanvpetrov Feb 17, 2025
59fd55a
docs(query-builder): improved keyboard interaction text
ivanvpetrov Feb 17, 2025
601182a
docs(query-builder): update styling code-snippets
teodosiah Feb 17, 2025
1dce3df
Update en/components/query-builder.md
igdmdimitrov Feb 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 167 additions & 26 deletions en/components/query-builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The [`IgxQueryBuilderComponent`]({environment:angularApiUrl}/classes/igxquerybui

## Angular Query Builder Example

We’ve created this Angular Query Builder example to show you the default functionalities of the Angular Query Builder component. Click the plus button to add conditions, “and” group as well as “or” group. Navigate the side bars to ungroup or delete.
We’ve created this Angular Query Builder example to show you the default functionalities of the Angular Query Builder component. Click the plus button to add conditions, “and” group as well as “or” group. Grouping or ungrouping expressions as well as re-ordering could be achieved via the Drag&Drop functionality.

<code-view style="height:530px"
data-demos-base-url="{environment:demosBaseUrl}"
Expand Down Expand Up @@ -63,7 +63,7 @@ import { IGX_QUERY_BUILDER_DIRECTIVES, FilteringExpressionsTree, FieldType } fro
selector: 'app-home',
template: `
<igx-query-builder #queryBuilder
[fields]="fields"
[entities]="entities"
[(expressionTree)]="expressionTree"
(expressionTreeChange)="onExpressionTreeChange()">
</igx-query-builder>
Expand All @@ -75,7 +75,7 @@ import { IGX_QUERY_BUILDER_DIRECTIVES, FilteringExpressionsTree, FieldType } fro
})
export class HomeComponent {
public expressionTree: FilteringExpressionsTree;
public fields: FieldType [];
public entities: Array<any>;

public onExpressionTreeChange() {
...
Expand All @@ -87,40 +87,50 @@ Now that you have the Ignite UI for Angular Query Builder module or directives i

## Using the Angular Query Builder

If no expression tree is initially set, you start with creating a group of conditions linked with [`AND`]({environment:angularApiUrl}/enums/filteringlogic.html#and) or [`OR`]({environment:angularApiUrl}/enums/filteringlogic.html#or). After that, conditions or sub-groups can be added.
If no expression tree is initially set, you start by choosing an entity and which of its fields the query should return. After that, conditions or sub-groups can be added.

In order to add a condition, a field, an operand based on the field dataType and a value if the operand is not unary. Once the condition is committed, a chip with the condition information appears. By hovering or clicking the chip, you have the options to modify it or add another condition or group right after it.
In order to add a condition you select a field, an operand based on the field data type and a value if the operand is not unary. The operands `In` and `Not In` will allow you to create an inner query with conditions for a different entity instead of simply providing a value. Once the condition is committed, a chip with the condition information appears. By clicking or hovering the chip, you have the options to modify it or add another condition or group right after it.

If you select more than one condition chip, a context menu appears with options to create a group or delete the queries. If you choose to create a group with the selected conditions, the newly created group will appear where the topmost selected condition was placed.
Clicking on the ([`AND`]({environment:angularApiUrl}/enums/filteringlogic.html#and) or [`OR`]({environment:angularApiUrl}/enums/filteringlogic.html#or)) button placed above each group, will open a menu with options to change the group type or ungroup the conditions inside.

In order to select a group, you can also click on its vertical line, which is colored based on the linking condition ([`AND`]({environment:angularApiUrl}/enums/filteringlogic.html#and) or [`OR`]({environment:angularApiUrl}/enums/filteringlogic.html#or)). If a single group is selected, you get a context menu with options to change its logic, ungroup or delete it.
Since every condition is related to a specific field from a particular entity changing the entity will lead to resetting all preset conditions and groups. When selecting a new entity a confirmation dialog will be shown, unless the [`showEntityChangeDialog`]({environment:angularApiUrl}/classes/igxquerybuildercomponent.html#showEntityChangeDialog) input property is set to false.

You can start using the component by setting the [`fields`]({environment:angularApiUrl}/classes/igxquerybuildercomponent.html#fields) property to an array describing the field name and its data type. It will automatically assign the corresponding operands based on the data type.
You can start using the component by setting the [`entities`]({environment:angularApiUrl}/classes/igxquerybuildercomponent.html#entities) property to an array describing the entity name and an array of its fields, where each field is defined by its name and data type. Once a field is selected it will automatically assign the corresponding operands based on the data type.
The Query Builder has the [`expressionTree`]({environment:angularApiUrl}/classes/igxquerybuildercomponent.html#expressionTree) input property. You could use it to set an initial state of the control and access the user-specified filtering logic.

```typescript
ngAfterViewInit(): void {
const tree = new FilteringExpressionsTree(FilteringLogic.And);
const innerTree = new FilteringExpressionsTree(FilteringLogic.And, undefined, 'Companies', ['ID']);
innerTree.filteringOperands.push({
fieldName: 'Employees',
condition: IgxNumberFilteringOperand.instance().condition('greaterThan'),
conditionName: 'greaterThan',
searchVal: 100
});
innerTree.filteringOperands.push({
fieldName: 'Contact',
condition: IgxBooleanFilteringOperand.instance().condition('true'),
conditionName: 'true'
});

const tree = new FilteringExpressionsTree(FilteringLogic.And, undefined, 'Orders', ['*']);
tree.filteringOperands.push({
fieldName: 'ID',
condition: IgxStringFilteringOperand.instance().condition('contains'),
searchVal: 'a',
ignoreCase: true
fieldName: 'CompanyID',
condition: IgxStringFilteringOperand.instance().condition('in'),
conditionName: 'in',
searchTree: innerTree
});
const subTree = new FilteringExpressionsTree(FilteringLogic.Or);
subTree.filteringOperands.push({
fieldName: 'ContactTitle',
condition: IgxStringFilteringOperand.instance().condition('doesNotContain'),
searchVal: 'b',
ignoreCase: true
tree.filteringOperands.push({
fieldName: 'OrderDate',
condition: IgxDateFilteringOperand.instance().condition('before'),
conditionName: 'before',
searchVal: new Date('2024-01-01T00:00:00.000Z')
});
subTree.filteringOperands.push({
fieldName: 'CompanyName',
condition: IgxStringFilteringOperand.instance().condition('startsWith'),
searchVal: 'c',
ignoreCase: true
tree.filteringOperands.push({
fieldName: 'ShippedDate',
condition: IgxDateFilteringOperand.instance().condition('null'),
conditionName: 'null'
});
tree.filteringOperands.push(subTree);

this.queryBuilder.expressionTree = tree;
}
Expand All @@ -129,10 +139,139 @@ ngAfterViewInit(): void {
The `expressionTree` is a two-way bindable property which means a corresponding `expressionTreeChange` output is implemented that emits when the end-user changes the UI by creating, editing or removing conditions. It can also be subscribed to separately to receive notifications and react to such changes.

```html
<igx-query-builder #queryBuilder [fields]="fields" [(expressionTree)]="expressionTree" (expressionTreeChange)="onExpressionTreeChange()">
<igx-query-builder #queryBuilder
[entities]="entities"
[(expressionTree)]="expressionTree"
(expressionTreeChange)="onExpressionTreeChange()">
</igx-query-builder>
```

## Expressions Dragging

With the [*Drag & Drop*](drag-drop.md) functionality, users can easily reposition condition chips to adjust their query logic dynamically.
Chips can be dragged along the whole query tree, including in groups and subgroups.
##### Notes
- Dragging a chip does not modify its condition, only its position.
- In the main query, changes take effect immediately after dropping a chip. In inner queries, user has to commit the inner query after repositioning the chip.
- Chip can also be dragged in a newly created group to achieve condition grouping.
- Chips from one query tree cannot be dragged in another, e.g. from parent to inner and vice versa.
<div style="display:inline-block;">
<a style="background: url(../../images/general/query-builder-drag-and-drop.gif); display:flex; justify-content:center; width: 80vw; max-width:480px; min-height:415px;"
target="_blank">
<img src="../images/general/play.svg" style="vertical-align: middle;" />
</a>
<p style="text-align:center;">Rearranging chips using mouse Drag and Drop</p>
</div>

### Keyboard reordering
Similar to mouse Drag & Drop, user can use the keyboard to rearrange condition chips.
##### How It Works
1. **Start:** Using <kbd>Tab</kbd> / <kbd>Shift + Tab</kbd> navigate to a chip's, drag indicator.
2. **Move Up/Down:** With <kbd>Arrow Down</kbd>/<kbd>Arrow Up</kbd> move the chip to a new position.
3. **Confirm position:** Pressing <kbd>Space</kbd> / <kbd>Enter</kbd> confirms the new position.
4. **Canceling:** By hitting <kbd>Esc</kbd>, user can cancel keyboard repositioning. The chip returns to it's original position.
<div style="display:inline-block;">
<a style="background: url(../../images/general/query-builder-keyboard-drag-and-drop.gif); display:flex; justify-content:center; width: 80vw; max-width:320px; min-height:262px;"
target="_blank">
<img src="../images/general/play.svg" style="vertical-align: middle;" />
</a>
<p style="text-align:center;">Rearranging chips using keyboard reordering</p>
</div>

## Keyboard interaction
**Key Combinations**
- <kbd>Arrow Down</kbd> -
- <kbd>Arrow Up</kbd> -
- <kbd>Tab</kbd> / <kbd>Shift + Tab</kbd> - navigates to the next/previous chip, drag indicator and remove button
- <kbd>Space</kbd> / <kbd>Enter</kbd> - focused expression enters edit mode

## Templating

The Ignite UI for Angular Query Builder Component allows defining templates for the component's header and the search value using the following predefined reference names:

### Header

Passing content inside of the `igx-query-builder-header` allows templating the query builder header.

The code snippet below illustrates how to do this:

```html
<igx-query-builder #queryBuilder [entities]="this.entities">
<igx-query-builder-header [title]="'Query Builder Template Sample'">
</igx-query-builder-header>
</igx-query-builder>
```

### Search value

The search value of a condition can be templated using the [`igxQueryBuilderSearchValue`]({environment:angularApiUrl}/classes/igxquerybuildersearchvaluetemplatedirective.html) directive, applied to an `<ng-template>` inside of the `igx-query-builder`'s body:

```html
<igx-query-builder #queryBuilder
[entities]="entities"
[expressionTree]="expressionTree">
<ng-template #searchValueTemplate igxQueryBuilderSearchValue
let-searchValue
let-selectedField = "selectedField"
let-selectedCondition = "selectedCondition"
let-defaultSearchValueTemplate = "defaultSearchValueTemplate">
@if (
selectedField?.field === 'Region' &&
(selectedCondition === 'equals' || selectedCondition === 'doesNotEqual')
){
<igx-select [placeholder]="'Select region'" [(ngModel)]="searchValue.value">
<igx-select-item *ngFor="let reg of regionOptions" [value]="reg">
{{ reg.text }}
</igx-select-item>
</igx-select>
}
@else if (
selectedField?.field === 'OrderStatus' &&
(selectedCondition === 'equals' || selectedCondition === 'doesNotEqual')
){
<igx-radio-group>
<igx-radio class="radio-sample" *ngFor="let stat of statusOptions" value="{{stat.value}}" [(ngModel)]="searchValue.value">
{{stat.text}}
</igx-radio>
</igx-radio-group>
}
@else {
<ng-container #defaultTemplate *ngTemplateOutlet="defaultSearchValueTemplate"></ng-container>
}
</ng-template>
</igx-query-builder>
```

## Formatter
In order to change the appearance of the search value in the chip displayed when a condition is not in edit mode, you can set a formatter function to the fields array. The search value and selected condition could be acccessed through the value and rowData arguments as follows:

```ts
this.ordersFields = [
{ field: "CompanyID", dataType: "string" },
{ field: "OrderID", dataType: "number" },
{ field: "EmployeeId", dataType: "number" },
{ field: "OrderDate", dataType: "date" },
{ field: "RequiredDate", dataType: "date" },
{ field: "ShippedDate", dataType: "date" },
{ field: "ShipVia", dataType: "number" },
{ field: "Freight", dataType: "number" },
{ field: "ShipName", dataType: "string" },
{ field: "ShipCity", dataType: "string" },
{ field: "ShipPostalCode", dataType: "string" },
{ field: "ShipCountry", dataType: "string" },
{ field: "Region", dataType: "string", formatter: (value: any, rowData: any) => rowData === 'equals' || rowData === 'doesNotEqual' ? `${value.value}` : value }},
{ field: "OrderStatus", dataType: "number" }
];
```

## Demo
We’ve created this Angular Query Builder example to show you the templating and formatter functionalities for the header and the search value of the Angular Query Builder component.

<code-view style="height:530px"
data-demos-base-url="{environment:demosBaseUrl}"
iframe-src="{environment:demosBaseUrl}/interactions/query-builder-template-sample" alt="Angular Query Builder Templates Example">
</code-view>

## Styling

To get started with styling the Query Builder, we need to import the `index` file, where all the theme functions and component mixins live:
Expand Down Expand Up @@ -225,6 +364,8 @@ You can also streamline your Angular app development using [WYSIWYG App Builder
<div class="divider--half"></div>

* [IgxQueryBuilderComponent API]({environment:angularApiUrl}/classes/igxquerybuildercomponent.html)
* [IgxQueryBuilderHeaderComponent]({environment:angularApiUrl}/classes/igxquerybuilderheadercomponent.html)
* [IgxQueryBuilderSearchValueTemplateDirective]({environment:angularApiUrl}/classes/igxquerybuildersearchvaluetemplatedirective.html)
* [IgxQueryBuilderComponent Styles]({environment:sassApiUrl}/index.html#function-query-builder-theme)

## Additional Resources
Expand Down
1 change: 1 addition & 0 deletions en/components/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,7 @@
- name: Query Builder
href: query-builder.md
new: false
updated: true
- name: Radio & Radio Group
href: radio-button.md
new: false
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading