• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IgniteUI / igniteui-angular / 20960087204

13 Jan 2026 02:19PM UTC coverage: 12.713% (-78.8%) from 91.5%
20960087204

Pull #16746

github

web-flow
Merge 9afce6e5d into a967f087e
Pull Request #16746: fix(csv): export summaries - master

1008 of 16803 branches covered (6.0%)

19 of 23 new or added lines in 2 files covered. (82.61%)

24693 existing lines in 336 files now uncovered.

3985 of 31345 relevant lines covered (12.71%)

2.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

1.56
/projects/igniteui-angular/query-builder/src/query-builder/query-builder.component.ts
1
import { booleanAttribute, ContentChild, EventEmitter, Output, TemplateRef, inject } from '@angular/core';
2
import {
3
    Component, Input, ViewChild, ElementRef, OnDestroy, HostBinding
4
} from '@angular/core';
5
import { Subject } from 'rxjs';
6
import {
7
    EntityType,
8
    FieldType,
9
    IExpressionTree,
10
    IQueryBuilderResourceStrings,
11
    QueryBuilderResourceStringsEN,
12
    recreateTree,
13
    IgxOverlayOutletDirective,
14
    getCurrentResourceStrings,
15
    onResourceChangeHandle
16
} from 'igniteui-angular/core';
17
import { IgxQueryBuilderTreeComponent } from './query-builder-tree.component';
18
import { IgxIconService } from 'igniteui-angular/icon';
19
import { editor } from '@igniteui/material-icons-extended';
20
import { IgxQueryBuilderSearchValueTemplateDirective } from './query-builder.directives';
21

22
/**
23
 * A component used for operating with complex filters by creating or editing conditions
24
 * and grouping them using AND/OR logic.
25
 * It is used internally in the Advanced Filtering of the Grid.
26
 *
27
 * @example
28
 * ```html
29
 * <igx-query-builder [entities]="this.entities">
30
 * </igx-query-builder>
31
 * ```
32
 */
33
@Component({
34
    selector: 'igx-query-builder',
35
    templateUrl: './query-builder.component.html',
36
    imports: [IgxQueryBuilderTreeComponent]
37
})
38
export class IgxQueryBuilderComponent implements OnDestroy {
3✔
UNCOV
39
    protected iconService = inject(IgxIconService);
×
40

41
    /**
42
     * @hidden @internal
43
     */
44
    @HostBinding('class.igx-query-builder')
UNCOV
45
    public cssClass = 'igx-query-builder';
×
46

47
    /**
48
     * @hidden @internal
49
     */
50
    @HostBinding('style.display')
UNCOV
51
    public display = 'block';
×
52

53
    /**
54
     * Gets/sets whether the confirmation dialog should be shown when changing entity.
55
     * Default value is `true`.
56
     */
57
    @Input({ transform: booleanAttribute })
UNCOV
58
    public showEntityChangeDialog = true;
×
59

60
    /**
61
     * Gets the list of entities available for the IgxQueryBuilderComponent.
62
     *
63
     * Each entity describes a logical group of fields that can be used in queries.
64
     * An entity can optionally have child entities, allowing nested sub-queries.
65
     *
66
     * @returns An array of {@link EntityType} objects.
67
     */
68
    public get entities(): EntityType[] {
UNCOV
69
        return this._entities;
×
70
    }
71

72
    /**
73
     * Sets the list of entities for the IgxQueryBuilderComponent.
74
     * If the `expressionTree` is defined, it will be recreated with the new entities.
75
     *
76
     * Each entity should be an {@link EntityType} object describing the fields and optionally child entities.
77
     *
78
     * Example:
79
     * ```ts
80
     * [
81
     *   {
82
     *     name: 'Orders',
83
     *     fields: [{ field: 'OrderID', dataType: 'number' }],
84
     *     childEntities: [
85
     *       {
86
     *         name: 'OrderDetails',
87
     *         fields: [{ field: 'ProductID', dataType: 'number' }]
88
     *       }
89
     *     ]
90
     *   }
91
     * ]
92
     * ```
93
     *
94
     * @param entities - The array of entities to set.
95
     */
96
    @Input()
97
    public set entities(entities: EntityType[]) {
UNCOV
98
        if (entities !== this._entities) {
×
UNCOV
99
            if (entities && this.expressionTree) {
×
100
                this._expressionTree = recreateTree(this._expressionTree, entities);
×
101
            }
102
        }
UNCOV
103
        this._entities = entities;
×
104
    }
105

106
    /**
107
     * Gets the list of fields for the QueryBuilder.
108
     *
109
     * @deprecated since version 19.1.0. Use the `entities` property instead.
110
     * @hidden
111
     */
112
    public get fields(): FieldType[] {
113
        return this._fields;
×
114
    }
115

116
    /**
117
     * Sets the list of fields for the QueryBuilder.
118
     * Automatically wraps them into a single entity to maintain backward compatibility.
119
     *
120
     * @param fields - The array of fields to set.
121
     * @deprecated since version 19.1.0. Use the `entities` property instead.
122
     * @hidden
123
     */
124
    @Input()
125
    public set fields(fields: FieldType[]) {
126
        if (fields) {
×
127
            this._fields = fields;
×
128
            this.entities = [
×
129
                {
130
                    name: null,
131
                    fields: fields
132
                }
133
            ];
134
        }
135
    }
136

137
    /**
138
    * Returns the expression tree.
139
    */
140
    public get expressionTree(): IExpressionTree {
UNCOV
141
        return this._expressionTree;
×
142
    }
143

144
    /**
145
     * Sets the expression tree.
146
     */
147
    @Input()
148
    public set expressionTree(expressionTree: IExpressionTree) {
UNCOV
149
        if (expressionTree !== this._expressionTree) {
×
UNCOV
150
            if (this.entities && expressionTree) {
×
UNCOV
151
                this._expressionTree = recreateTree(expressionTree, this.entities);
×
152
            } else {
UNCOV
153
                this._expressionTree = expressionTree;
×
154
            }
155
        }
156
    }
157

158
    /**
159
     * Gets the `locale` of the query builder.
160
     * If not set, defaults to application's locale.
161
     */
162
    @Input()
163
    public locale: string;
164

165
    /**
166
     * Sets the resource strings.
167
     * By default it uses EN resources.
168
     */
169
    @Input()
170
    public set resourceStrings(value: IQueryBuilderResourceStrings) {
UNCOV
171
        this._resourceStrings = Object.assign({}, this._resourceStrings, value);
×
172
    }
173

174
    /**
175
     * Returns the resource strings.
176
     */
177
    public get resourceStrings(): IQueryBuilderResourceStrings {
UNCOV
178
        return this._resourceStrings || this._defaultResourceStrings;
×
179
    }
180

181
    /**
182
     * Disables subsequent entity changes at the root level after the initial selection.
183
     */
184
    @Input()
UNCOV
185
    public disableEntityChange = false;
×
186

187
    /**
188
     * Disables return fields changes at the root level.
189
     */
190
     @Input()
UNCOV
191
     public disableReturnFieldsChange = false;
×
192

193
    /**
194
     * Event fired as the expression tree is changed.
195
     *
196
     * ```html
197
     *  <igx-query-builder (expressionTreeChange)='onExpressionTreeChange()'></igx-query-builder>
198
     * ```
199
     */
200
    @Output()
UNCOV
201
    public expressionTreeChange = new EventEmitter<IExpressionTree>();
×
202

203
    /**
204
     * @hidden @internal
205
     */
206
    @ContentChild(IgxQueryBuilderSearchValueTemplateDirective, { read: TemplateRef })
207
    public searchValueTemplate: TemplateRef<any>;
208

209
    /**
210
     * @hidden @internal
211
     */
212
    @ViewChild(IgxQueryBuilderTreeComponent)
213
    public queryTree: IgxQueryBuilderTreeComponent;
214

UNCOV
215
    private destroy$ = new Subject<any>();
×
UNCOV
216
    private _resourceStrings: IQueryBuilderResourceStrings = null;
×
UNCOV
217
    private _defaultResourceStrings = getCurrentResourceStrings(QueryBuilderResourceStringsEN);
×
218
    private _expressionTree: IExpressionTree;
219
    private _fields: FieldType[];
220
    private _entities: EntityType[];
UNCOV
221
    private _shouldEmitTreeChange = true;
×
222

223
    constructor() {
UNCOV
224
        this.registerSVGIcons();
×
UNCOV
225
        onResourceChangeHandle(this.destroy$, () => {
×
UNCOV
226
            this._defaultResourceStrings = getCurrentResourceStrings(QueryBuilderResourceStringsEN, false);
×
227
        }, this);
228
    }
229

230
    /**
231
     * Returns whether the expression tree can be committed in the current state.
232
     */
233
    public canCommit(): boolean {
UNCOV
234
        return this.queryTree?.canCommitCurrentState() === true;
×
235
    }
236

237
    /**
238
     * Commits the expression tree in the current state if it is valid. If not throws an exception.
239
     */
240
    public commit(): void {
UNCOV
241
        if (this.canCommit()) {
×
UNCOV
242
            this._shouldEmitTreeChange = false;
×
UNCOV
243
            this.queryTree.commitCurrentState();
×
UNCOV
244
            this._shouldEmitTreeChange = true;
×
245
        } else {
UNCOV
246
            throw new Error('Expression tree can\'t be committed in the current state. Use `canCommit` method to check if the current state is valid.');
×
247
        }
248
    }
249

250
    /**
251
     * Discards all unsaved changes to the expression tree.
252
     */
253
    public discard(): void {
UNCOV
254
        this.queryTree.cancelOperandEdit();
×
255
    }
256

257
    /**
258
     * @hidden @internal
259
     */
260
    public ngOnDestroy(): void {
UNCOV
261
        this.destroy$.next(true);
×
UNCOV
262
        this.destroy$.complete();
×
263
    }
264

265
    /**
266
     * @hidden @internal
267
     *
268
     * used by the grid
269
     */
270
    public setPickerOutlet(outlet?: IgxOverlayOutletDirective | ElementRef) {
UNCOV
271
        this.queryTree.setPickerOutlet(outlet);
×
272
    }
273

274
    /**
275
     * @hidden @internal
276
     *
277
     * used by the grid
278
     */
279
    public get isContextMenuVisible(): boolean {
280
        return this.queryTree.isContextMenuVisible;
×
281
    }
282

283
    /**
284
     * @hidden @internal
285
     *
286
     * used by the grid
287
     */
288
    public exitOperandEdit() {
UNCOV
289
        this.queryTree.exitOperandEdit();
×
290
    }
291

292
    /**
293
     * @hidden @internal
294
     *
295
     * used by the grid
296
     */
297
    public setAddButtonFocus() {
UNCOV
298
        this.queryTree.setAddButtonFocus();
×
299
    }
300

301
    public onExpressionTreeChange(tree: IExpressionTree) {
UNCOV
302
        if (tree && this.entities && tree !== this._expressionTree) {
×
UNCOV
303
            this._expressionTree = recreateTree(tree, this.entities);
×
304
        } else {
UNCOV
305
            this._expressionTree = tree;
×
306
        }
UNCOV
307
        if (this._shouldEmitTreeChange) {
×
UNCOV
308
            this.expressionTreeChange.emit(tree);
×
309
        }
310
    }
311

312
    private registerSVGIcons(): void {
UNCOV
313
        const editorIcons = editor as any[];
×
314

UNCOV
315
        editorIcons.forEach((icon) => {
×
UNCOV
316
            this.iconService.addSvgIconFromText(icon.name, icon.value, 'imx-icons');
×
UNCOV
317
            this.iconService.addIconRef(icon.name, 'default', {
×
318
                name: icon.name,
319
                family: 'imx-icons'
320
            });
321
        });
322

UNCOV
323
        const inIcon = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#5f6368"><path d="M560-280H120v-400h720v120h-80v-40H200v240h360v80Zm-360-80v-240 240Zm560 200v-120H640v-80h120v-120h80v120h120v80H840v120h-80Z"/></svg>';
×
UNCOV
324
        this.iconService.addSvgIconFromText('in', inIcon, 'imx-icons');
×
UNCOV
325
        this.iconService.addIconRef('in', 'default', {
×
326
            name: 'in',
327
            family: 'imx-icons'
328
        });
329

UNCOV
330
        const notInIcon = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#5f6368"><path d="M560-280H120v-400h720v120h-80v-40H200v240h360v80Zm-360-80v-240 240Zm440 104 84-84-84-84 56-56 84 84 84-84 56 56-83 84 83 84-56 56-84-83-84 83-56-56Z"/></svg>';
×
UNCOV
331
        this.iconService.addSvgIconFromText('not-in', notInIcon, 'imx-icons');
×
UNCOV
332
        this.iconService.addIconRef('not-in', 'default', {
×
333
            name: 'not-in',
334
            family: 'imx-icons'
335
        });
336

UNCOV
337
        this.iconService.addIconRef('add', 'default', {
×
338
            name: 'add',
339
            family: 'material',
340
        });
341

UNCOV
342
        this.iconService.addIconRef('close', 'default', {
×
343
            name: 'close',
344
            family: 'material',
345
        });
346

UNCOV
347
        this.iconService.addIconRef('check', 'default', {
×
348
            name: 'check',
349
            family: 'material',
350
        });
351

UNCOV
352
        this.iconService.addIconRef('delete', 'default', {
×
353
            name: 'delete',
354
            family: 'material',
355
        });
356

UNCOV
357
        this.iconService.addIconRef('edit', 'default', {
×
358
            name: 'edit',
359
            family: 'material',
360
        });
361
    }
362
}
363

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc