Visão geral do componente Angular Query Builder

    Angular Query Builder faz parte dos nossos Angular Components e fornece uma UI rica que permite aos desenvolvedores criar consultas complexas de filtragem de dados para um conjunto de dados especificado. Com este componente, eles podem criar uma árvore de expressões e definir condições AND/OR entre elas com editores e listas de condições determinadas pelo tipo de dados de cada campo. A árvore de expressão pode então ser facilmente transformada em uma consulta no formato que o backend suporta.

    O componente IgxQueryBuilderComponent fornece uma maneira de construir consultas complexas por meio da UI. Ao especificar operadores AND/OR, condições e valores, o usuário cria uma árvore de expressão que descreve a consulta.

    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. Grouping or ungrouping expressions as well as re-ordering could be achieved via the Drag&Drop functionality.

    Getting Started with Ignite UI for Angular Query Builder

    Para começar a usar o componente Ignite UI for Angular Query Builder, primeiro você precisa instalar Ignite UI for Angular. Em um aplicativo Angular existente, digite o seguinte comando:

    ng add igniteui-angular
    

    Para obter uma introdução completa ao Ignite UI for Angular, leia o tópico de introdução.

    O próximo passo é importar o IgxQueryBuilderModule no arquivo app.module.ts.

    // app.module.ts
    
    import { IgxQueryBuilderModule } from 'igniteui-angular';
    // import { IgxQueryBuilderModule } from '@infragistics/igniteui-angular'; for licensed package
    
    @NgModule({
        ...
        imports: [..., IgxQueryBuilderModule],
        ...
    })
    export class AppModule {}
    

    Como alternativa, a partir da 16.0.0 você pode importar o IgxQueryBuilderComponent como uma dependência autônoma ou usar o token IGX_QUERY_BUILDER_DIRECTIVES para importar o componente e todos os seus componentes e diretivas de suporte.

    // home.component.ts
    
    import { IGX_QUERY_BUILDER_DIRECTIVES, FilteringExpressionsTree, FieldType } from 'igniteui-angular';
    // import { IGX_QUERY_BUILDER_DIRECTIVES, FilteringExpressionsTree, FieldType } from '@infragistics/igniteui-angular'; for licensed package
    
    @Component({
        selector: 'app-home',
        template: `
        <igx-query-builder #queryBuilder
            [entities]="entities"
            [(expressionTree)]="expressionTree"
            (expressionTreeChange)="onExpressionTreeChange()">
        </igx-query-builder>
        `,
        styleUrls: ['home.component.scss'],
        standalone: true,
        imports: [IGX_QUERY_BUILDER_DIRECTIVES]
        /* or imports: [IgxQueryBuilderComponent] */
    })
    export class HomeComponent {
        public expressionTree: FilteringExpressionsTree;
        public entities: Array<any>;
    
        public onExpressionTreeChange() {
            ...
        }
    }
    

    Agora que você importou o módulo Ignite UI for Angular Query Builder ou as diretivas, você pode começar a usar o componente igx-query-builder.

    Using the Angular Query Builder

    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 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.

    Clicking on the (AND or OR) button placed above each group, will open a menu with options to change the group type or ungroup the conditions inside.

    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 input property is set to false.

    You can start using the component by setting the 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 input property. You could use it to set an initial state of the control and access the user-specified filtering logic.

    ngAfterViewInit(): void {
        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: 'CompanyID',
            condition: IgxStringFilteringOperand.instance().condition('inQuery'),
            conditionName: 'inQuery',
            searchTree: innerTree
        });
        tree.filteringOperands.push({
            fieldName: 'OrderDate',
            condition: IgxDateFilteringOperand.instance().condition('before'),
            conditionName: 'before',
            searchVal: new Date('2024-01-01T00:00:00.000Z')
        });
        tree.filteringOperands.push({
            fieldName: 'ShippedDate',
            condition: IgxDateFilteringOperand.instance().condition('null'),
            conditionName: 'null'
        });
    
        this.queryBuilder.expressionTree = tree;
    }
    

    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 separately to receive notifications and react to such changes.

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

    Expressions Dragging

    Condition chips can be easily repositioned using mouse Drag & Drop or Keyboard reordering approaches. With those, users can adjust their query logic dynamically.

    • Dragging a chip does not modify its condition/contents, only its position.
    • Chip can also be dragged along groups and subgroups. For example, grouping/ungrouping expressions is achieved via the Expressions Dragging functionality. In order to group already existing conditions, first you need to add a new group through the 'add' group button. Then via dragging, the required expressions can be moved to that group. In order to ungroup, you could drag all conditions outside their current group and once the last condition is moved out, the group will be deleted.
    Note

    Chips from one query tree cannot be dragged in another, e.g. from parent to inner and vice versa.

    Keyboard interaction

    Key Combinations

    • Tab / Shift + Tab - navigates to the next/previous chip, drag indicator, remove button, 'add' expression button.
    • Arrow Down/Arrow Up - when chip's drag indicator is focused, the chip can be moved up/down.
    • Space / Enter - focused expression enters edit mode. If chip is been moved, this confirms it's new position.
    • Esc - chip's reordering is canceled and it returns to it's original position.
    Note

    Keyboard reordering provides the same functionality as mouse Drag & Drop. Once a chip is moved, user has to confirm the new position or cancel the reorder.

    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 Template

    By default the IgxQueryBuilderComponent header would not be displayed. In order to define such, the IgxQueryBuilderHeaderComponent should be added inside of the igx-query-builder.

    Then, for setting the header title could be used the title input and passing content inside of the igx-query-builder-header allows templating the query builder header.

    The code snippet below illustrates how to do this:

    <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 directive, applied to an <ng-template> inside of the igx-query-builder's body:

    <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:

    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.

    Estilização

    Para começar a estilizar o Query Builder, precisamos importar o arquivo index, onde todas as funções do tema e mixins de componentes estão localizados:

    @use "igniteui-angular/theming" as *;
    
    // IMPORTANT: Prior to Ignite UI for Angular version 13 use:
    // @import '~igniteui-angular/lib/core/styles/themes/index';
    

    O Query Builder pega sua cor de fundo do seu tema, usando o parâmetro background. Para alterar o fundo, precisamos criar um tema personalizado:

    
    $custom-query-builder: query-builder-theme(
      $background: #292826,
      ...
    );
    

    Como temos outros componentes dentro do Query Builder, como botões, chips, menus suspensos e entradas, precisamos criar um tema separado para cada um:

    $custom-button: button-theme(
      $schema: $dark-material-schema,
      $background: #292826,
      $foreground: #ffcd0f,
      ...
    );
    
    $custom-input-group: input-group-theme(
      $focused-secondary-color: #ffcd0f
    );
    
    $custom-chip: chip-theme(
      $background: #ffcd0f,
      $text-color: #292826
    );
    
    $custom-icon-button: icon-button-theme(
      $background: #ffcd0f,
      $foreground: #292826
    );
    

    In this example we only changed some of the parameters for the listed components, but the button-theme, chip-theme, drop-down-theme, input-group-theme themes provide way more parameters to control their respective styling.

    Note

    Em vez de codificar os valores de cor como acabamos de fazer, podemos obter maior flexibilidade em termos de cores usando as palette funções e color. Consulte o Palettes tópico para obter orientações detalhadas sobre como usá-los.

    O último passo é incluir os novos temas de componentes usando o mixin css-vars.

    @include css-vars($custom-query-builder);
    
    :host {
      ::ng-deep {
        @include css-vars($custom-input-group);
        @include css-vars($custom-chip);
        @include css-vars($custom-icon-button);
    
        .igx-filter-tree__buttons {
          @include css-vars($custom-button);
        }
      }
    }
    
    Note

    Se o componente estiver usando um Emulated ViewEncapsulation, é necessário penetrate esse encapsulamento usando::ng-deep para estilizar os componentes dentro do componente do construtor de consultas (botão, chip, menu suspenso, etc.).

    Demo

    Note

    A amostra não será afetada Change Theme pelo tema global selecionado.

    Você também pode otimizar o desenvolvimento do seu aplicativo Angular usando o WYSIWYG App Builder ™ com componentes de interface de usuário reais.

    API References

    Additional Resources

    Nossa comunidade é ativa e sempre acolhedora para novas ideias.