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

IgniteUI / igniteui-angular / 13387853952

18 Feb 2025 09:55AM CUT coverage: 91.681% (+0.06%) from 91.622%
13387853952

Pull #14647

github

web-flow
Merge 54a18c10f into 10ddb05cf
Pull Request #14647: feat(query-builder): support for nested queries and other improvements

13326 of 15595 branches covered (85.45%)

901 of 977 new or added lines in 19 files covered. (92.22%)

1 existing line in 1 file now uncovered.

26881 of 29320 relevant lines covered (91.68%)

33936.7 hits per line

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

74.83
/projects/igniteui-angular/src/lib/data-operations/filtering-condition.ts
1
/**
2
 * Provides base filtering operations
3
 * Implementations should be Singleton
4
 *
5
 * @export
6
 */
7
export class IgxFilteringOperand {
8
    protected static _instance: IgxFilteringOperand = null;
2✔
9
    public operations: IFilteringOperation[];
10

11
    constructor() {
12
        this.operations = [{
15✔
13
            name: 'null',
14
            isUnary: true,
15
            iconName: 'filter_null',
16
            logic: (target: any) => target === null
66✔
17
        }, {
18
            name: 'notNull',
19
            isUnary: true,
20
            iconName: 'filter_not_null',
21
            logic: (target: any) => target !== null
82✔
22
        }, {
23
            name: 'in',
24
            isUnary: false,
25
            isNestedQuery: true,
26
            iconName: 'in',
27
            logic: (target: any, searchVal: Set<any>) => this.findValueInSet(target, searchVal)
343✔
28
        },
29
        {
30
            name: 'notIn',
31
            isUnary: false,
32
            isNestedQuery: true,
33
            iconName: 'not-in',
NEW
34
            logic: (target: any, searchVal: Set<any>) => !this.findValueInSet(target, searchVal)
×
35
        }];
36
    }
37

38
    public static instance(): IgxFilteringOperand {
39
        return this._instance || (this._instance = new this());
23,818✔
40
    }
41

42
    /**
43
     * Returns an array of names of the conditions which are visible in the filtering UI
44
     */
45
    public conditionList(): string[] {
46
        return this.operations.filter(f => !f.hidden && !f.isNestedQuery).map((element) => element.name);    
30,591✔
47
    }
48

49
    /**
50
     * Returns an array of names of the conditions which are visible in the UI, including "In" and "Not In", allowing the creation of sub-queries.
51
     */
52
    public extendedConditionList(): string[] {
53
        return this.operations.filter(f => !f.hidden).map((element) => element.name);
10,746✔
54
    }
55

56
    /**
57
     * Returns an instance of the condition with the specified name.
58
     *
59
     * @param name The name of the condition.
60
     */
61
    public condition(name: string): IFilteringOperation {
62
        return this.operations.find((element) => element.name === name);
386,658✔
63
    }
64

65
    /**
66
     * Adds a new condition to the filtering operations.
67
     *
68
     * @param operation The filtering operation.
69
     */
70
    public append(operation: IFilteringOperation) {
71
        this.operations.push(operation);
1✔
72
    }
73

74
    /**
75
     * @hidden
76
     */
77
    public findValueInSet(target: any, searchVal: Set<any>) {
78
        return searchVal.has(target);
327✔
79
    }
80
}
81

82
/* blazorCSSuppress */
83
/**
84
 * Provides filtering operations for booleans
85
 *
86
 * @export
87
 */
88
export class IgxBooleanFilteringOperand extends IgxFilteringOperand {
89
    protected constructor() {
90
        super();
2✔
91
        const newOperations: IFilteringOperation[] = [{
2✔
92
            name: 'all',
93
            isUnary: true,
94
            iconName: 'filter_all',
95
            logic: (_target: boolean) => true
16✔
96
        }, {
97
            name: 'true',
98
            isUnary: true,
99
            iconName: 'filter_true',
100
            logic: (target: boolean) => !!(target && target !== null && target !== undefined)
147✔
101
        }, {
102
            name: 'false',
103
            isUnary: true,
104
            iconName: 'filter_false',
105
            logic: (target: boolean) => !target && target !== null && target !== undefined
69✔
106
        }, {
107
            name: 'empty',
108
            isUnary: true,
109
            iconName: 'filter_empty',
110
            logic: (target: boolean) => target === null || target === undefined
75✔
111
        }, {
112
            name: 'notEmpty',
113
            isUnary: true,
114
            iconName: 'filter_not_empty',
115
            logic: (target: boolean) => target !== null && target !== undefined
14✔
116
        }];
117
        
118
        this.operations = newOperations.concat(this.operations);
2✔
119
    }
120
}
121

122
/* blazorCSSuppress */
123
/**
124
 * @internal
125
 * @hidden
126
 */
127
class IgxBaseDateTimeFilteringOperand extends IgxFilteringOperand {
128
    protected constructor() {
129
        super();
6✔
130
        const newOperations: IFilteringOperation[] = [{
6✔
131
            name: 'empty',
132
            isUnary: true,
133
            iconName: 'filter_empty',
134
            logic: (target: Date) => target === null || target === undefined
64✔
135
        }, {
136
            name: 'notEmpty',
137
            isUnary: true,
138
            iconName: 'filter_not_empty',
139
            logic: (target: Date) => target !== null && target !== undefined
38✔
140
        }];
141
        
142
        this.operations = newOperations.concat(this.operations);
6✔
143
    }
144

145
    /**
146
     * Splits a Date object into parts
147
     *
148
     * @memberof IgxDateFilteringOperand
149
     */
150
    public static getDateParts(date: Date, dateFormat?: string): IDateParts {
151
        const res = {
818✔
152
            day: null,
153
            hours: null,
154
            milliseconds: null,
155
            minutes: null,
156
            month: null,
157
            seconds: null,
158
            year: null
159
        };
160
        if (!date || !dateFormat) {
818!
161
            return res;
×
162
        }
163
        if (dateFormat.indexOf('y') >= 0) {
818✔
164
            res.year = date.getFullYear();
744✔
165
        }
166
        if (dateFormat.indexOf('M') >= 0) {
818✔
167
            res.month = date.getMonth();
624✔
168
        }
169
        if (dateFormat.indexOf('d') >= 0) {
818✔
170
            res.day = date.getDate();
480✔
171
        }
172
        if (dateFormat.indexOf('h') >= 0) {
818✔
173
            res.hours = date.getHours();
138✔
174
        }
175
        if (dateFormat.indexOf('m') >= 0) {
818✔
176
            res.minutes = date.getMinutes();
138✔
177
        }
178
        if (dateFormat.indexOf('s') >= 0) {
818✔
179
            res.seconds = date.getSeconds();
138✔
180
        }
181
        if (dateFormat.indexOf('f') >= 0) {
818!
182
            res.milliseconds = date.getMilliseconds();
×
183
        }
184
        return res;
818✔
185
    }
186

187
    /**
188
     * @hidden
189
     */
190
    public override findValueInSet(target: any, searchVal: Set<any>) {
191
        if (!target) {
×
192
            return false;
×
193
        }
194
        return searchVal.has((target instanceof Date) ? target.toISOString() : target);
×
195
    }
196

197
    protected validateInputData(target: Date) {
198
        if (!(target instanceof Date)) {
519!
199
            throw new Error('Could not perform filtering on \'date\' column because the datasource object type is not \'Date\'.');
×
200
        }
201
    }
202
}
203

204
/* blazorCSSuppress */
205
/**
206
 * Provides filtering operations for Dates
207
 *
208
 * @export
209
 */
210
export class IgxDateFilteringOperand extends IgxBaseDateTimeFilteringOperand {
211
    protected constructor() {
212
        super();
2✔
213
        const newOperations: IFilteringOperation[] = [{
2✔
214
            name: 'equals',
215
            isUnary: false,
216
            iconName: 'filter_equal',
217
            logic: (target: Date, searchVal: Date) => {
218
                if (!target) {
132✔
219
                    return false;
32✔
220
                }
221

222
                this.validateInputData(target);
100✔
223

224
                const targetp = IgxDateFilteringOperand.getDateParts(target, 'yMd');
100✔
225
                const searchp = IgxDateFilteringOperand.getDateParts(searchVal, 'yMd');
100✔
226
                return targetp.year === searchp.year &&
100✔
227
                    targetp.month === searchp.month &&
228
                    targetp.day === searchp.day;
229
            }
230
        }, {
231
            name: 'doesNotEqual',
232
            isUnary: false,
233
            iconName: 'filter_not_equal',
234
            logic: (target: Date, searchVal: Date) => {
235
                if (!target) {
34✔
236
                    return true;
8✔
237
                }
238

239
                this.validateInputData(target);
26✔
240

241
                const targetp = IgxDateFilteringOperand.getDateParts(target, 'yMd');
26✔
242
                const searchp = IgxDateFilteringOperand.getDateParts(searchVal, 'yMd');
26✔
243
                return targetp.year !== searchp.year ||
26✔
244
                    targetp.month !== searchp.month ||
245
                    targetp.day !== searchp.day;
246
            }
247
        }, {
248
            name: 'before',
249
            isUnary: false,
250
            iconName: 'filter_before',
251
            logic: (target: Date, searchVal: Date) => {
252
                if (!target) {
60✔
253
                    return false;
10✔
254
                }
255

256
                this.validateInputData(target);
50✔
257

258
                return target < searchVal;
50✔
259
            }
260
        }, {
261
            name: 'after',
262
            isUnary: false,
263
            iconName: 'filter_after',
264
            logic: (target: Date, searchVal: Date) => {
265
                if (!target) {
72✔
266
                    return false;
12✔
267
                }
268

269
                this.validateInputData(target);
60✔
270

271
                return target > searchVal;
60✔
272
            }
273
        }, {
274
            name: 'today',
275
            isUnary: true,
276
            iconName: 'filter_today',
277
            logic: (target: Date) => {
278
                if (!target) {
58✔
279
                    return false;
14✔
280
                }
281

282
                this.validateInputData(target);
44✔
283

284
                const d = IgxDateFilteringOperand.getDateParts(target, 'yMd');
44✔
285
                const now = IgxDateFilteringOperand.getDateParts(new Date(), 'yMd');
44✔
286
                return d.year === now.year &&
44✔
287
                    d.month === now.month &&
288
                    d.day === now.day;
289
            }
290
        }, {
291
            name: 'yesterday',
292
            isUnary: true,
293
            iconName: 'filter_yesterday',
294
            logic: (target: Date) => {
295
                if (!target) {
42✔
296
                    return false;
10✔
297
                }
298

299
                this.validateInputData(target);
32✔
300

301
                const td = IgxDateFilteringOperand.getDateParts(target, 'yMd');
32✔
302
                const y = ((d) => new Date(d.setDate(d.getDate() - 1)))(new Date());
32✔
303
                const yesterday = IgxDateFilteringOperand.getDateParts(y, 'yMd');
32✔
304
                return td.year === yesterday.year &&
32✔
305
                    td.month === yesterday.month &&
306
                    td.day === yesterday.day;
307
            }
308
        }, {
309
            name: 'thisMonth',
310
            isUnary: true,
311
            iconName: 'filter_this_month',
312
            logic: (target: Date) => {
313
                if (!target) {
26✔
314
                    return false;
6✔
315
                }
316

317
                this.validateInputData(target);
20✔
318

319
                const d = IgxDateFilteringOperand.getDateParts(target, 'yM');
20✔
320
                const now = IgxDateFilteringOperand.getDateParts(new Date(), 'yM');
20✔
321
                return d.year === now.year &&
20✔
322
                    d.month === now.month;
323
            }
324
        }, {
325
            name: 'lastMonth',
326
            isUnary: true,
327
            iconName: 'filter_last_month',
328
            logic: (target: Date) => {
329
                if (!target) {
42✔
330
                    return false;
10✔
331
                }
332

333
                this.validateInputData(target);
32✔
334

335
                const d = IgxDateFilteringOperand.getDateParts(target, 'yM');
32✔
336
                const now = IgxDateFilteringOperand.getDateParts(new Date(), 'yM');
32✔
337
                if (!now.month) {
32!
338
                    now.month = 11;
×
339
                    now.year -= 1;
×
340
                } else {
341
                    now.month--;
32✔
342
                }
343
                return d.year === now.year &&
32✔
344
                    d.month === now.month;
345
            }
346
        }, {
347
            name: 'nextMonth',
348
            isUnary: true,
349
            iconName: 'filter_next_month',
350
            logic: (target: Date) => {
351
                if (!target) {
26✔
352
                    return false;
6✔
353
                }
354

355
                this.validateInputData(target);
20✔
356

357
                const d = IgxDateFilteringOperand.getDateParts(target, 'yM');
20✔
358
                const now = IgxDateFilteringOperand.getDateParts(new Date(), 'yM');
20✔
359
                if (now.month === 11) {
20!
360
                    now.month = 0;
×
361
                    now.year += 1;
×
362
                } else {
363
                    now.month++;
20✔
364
                }
365
                return d.year === now.year &&
20✔
366
                    d.month === now.month;
367
            }
368
        }, {
369
            name: 'thisYear',
370
            isUnary: true,
371
            iconName: 'filter_this_year',
372
            logic: (target: Date) => {
373
                if (!target) {
26✔
374
                    return false;
6✔
375
                }
376

377
                this.validateInputData(target);
20✔
378

379
                const d = IgxDateFilteringOperand.getDateParts(target, 'y');
20✔
380
                const now = IgxDateFilteringOperand.getDateParts(new Date(), 'y');
20✔
381
                return d.year === now.year;
20✔
382
            }
383
        }, {
384
            name: 'lastYear',
385
            isUnary: true,
386
            iconName: 'filter_last_year',
387
            logic: (target: Date) => {
388
                if (!target) {
26✔
389
                    return false;
6✔
390
                }
391

392
                this.validateInputData(target);
20✔
393

394
                const d = IgxDateFilteringOperand.getDateParts(target, 'y');
20✔
395
                const now = IgxDateFilteringOperand.getDateParts(new Date(), 'y');
20✔
396
                return d.year === now.year - 1;
20✔
397
            }
398
        }, {
399
            name: 'nextYear',
400
            isUnary: true,
401
            iconName: 'filter_next_year',
402
            logic: (target: Date) => {
403
                if (!target) {
26✔
404
                    return false;
6✔
405
                }
406

407
                this.validateInputData(target);
20✔
408

409
                const d = IgxDateFilteringOperand.getDateParts(target, 'y');
20✔
410
                const now = IgxDateFilteringOperand.getDateParts(new Date(), 'y');
20✔
411
                return d.year === now.year + 1;
20✔
412
            }
413
        }];
414
        
415
        this.operations = newOperations.concat(this.operations);
2✔
416
    }
417

418
    public override findValueInSet(target: any, searchVal: Set<any>) {
419
        if (!target) {
16✔
420
            return false;
4✔
421
        }
422

423
        target = target.toDateString();
12✔
424
        return searchVal.has(target);
12✔
425
    }
426
}
427

428
/* blazorCSSuppress */
429
export class IgxDateTimeFilteringOperand extends IgxBaseDateTimeFilteringOperand {
430
    protected constructor() {
431
        super();
2✔
432
        const newOperations: IFilteringOperation[] = [{
2✔
433
            name: 'equals',
434
            isUnary: false,
435
            iconName: 'filter_equal',
436
            logic: (target: Date, searchVal: Date) => {
437
                if (!target) {
43✔
438
                    return false;
17✔
439
                }
440
                this.validateInputData(target);
26✔
441
                const targetp = IgxDateTimeFilteringOperand.getDateParts(target, 'yMdhms');
26✔
442
                const searchp = IgxDateTimeFilteringOperand.getDateParts(searchVal, 'yMdhms');
26✔
443
                return targetp.year === searchp.year &&
26✔
444
                    targetp.month === searchp.month &&
445
                    targetp.day === searchp.day &&
446
                    targetp.hours === searchp.hours &&
447
                    targetp.minutes === searchp.minutes &&
448
                    targetp.seconds === searchp.seconds;
449
            }
450
        }, {
451
            name: 'doesNotEqual',
452
            isUnary: false,
453
            iconName: 'filter_not_equal',
454
            logic: (target: Date, searchVal: Date) => {
455
                if (!target) {
8✔
456
                    return true;
2✔
457
                }
458
                this.validateInputData(target);
6✔
459
                const targetp = IgxDateTimeFilteringOperand.getDateParts(target, 'yMdhms');
6✔
460
                const searchp = IgxDateTimeFilteringOperand.getDateParts(searchVal, 'yMdhms');
6✔
461
                return targetp.year !== searchp.year ||
6✔
462
                    targetp.month !== searchp.month ||
463
                    targetp.day !== searchp.day ||
464
                    targetp.hours !== searchp.hours ||
465
                    targetp.minutes !== searchp.minutes ||
466
                    targetp.seconds !== searchp.seconds;
467
            }
468
        }, {
469
            name: 'before',
470
            isUnary: false,
471
            iconName: 'filter_before',
472
            logic: (target: Date, searchVal: Date) => {
473
                if (!target) {
×
474
                    return false;
×
475
                }
476

477
                this.validateInputData(target);
×
478

479
                return target < searchVal;
×
480
            }
481
        }, {
482
            name: 'after',
483
            isUnary: false,
484
            iconName: 'filter_after',
485
            logic: (target: Date, searchVal: Date) => {
486
                if (!target) {
×
487
                    return false;
×
488
                }
489

490
                this.validateInputData(target);
×
491

492
                return target > searchVal;
×
493
            }
494
        }, {
495
            name: 'today',
496
            isUnary: true,
497
            iconName: 'filter_today',
498
            logic: (target: Date) => {
499
                if (!target) {
8✔
500
                    return false;
2✔
501
                }
502

503
                this.validateInputData(target);
6✔
504

505
                const d = IgxDateTimeFilteringOperand.getDateParts(target, 'yMd');
6✔
506
                const now = IgxDateTimeFilteringOperand.getDateParts(new Date(), 'yMd');
6✔
507
                return d.year === now.year &&
6✔
508
                    d.month === now.month &&
509
                    d.day === now.day;
510
            }
511
        }, {
512
            name: 'yesterday',
513
            isUnary: true,
514
            iconName: 'filter_yesterday',
515
            logic: (target: Date) => {
516
                if (!target) {
×
517
                    return false;
×
518
                }
519

520
                this.validateInputData(target);
×
521

522
                const td = IgxDateTimeFilteringOperand.getDateParts(target, 'yMd');
×
523
                const y = ((d) => new Date(d.setDate(d.getDate() - 1)))(new Date());
×
524
                const yesterday = IgxDateTimeFilteringOperand.getDateParts(y, 'yMd');
×
525
                return td.year === yesterday.year &&
×
526
                    td.month === yesterday.month &&
527
                    td.day === yesterday.day;
528
            }
529
        }, {
530
            name: 'thisMonth',
531
            isUnary: true,
532
            iconName: 'filter_this_month',
533
            logic: (target: Date) => {
534
                if (!target) {
×
535
                    return false;
×
536
                }
537

538
                this.validateInputData(target);
×
539

540
                const d = IgxDateTimeFilteringOperand.getDateParts(target, 'yM');
×
541
                const now = IgxDateTimeFilteringOperand.getDateParts(new Date(), 'yM');
×
542
                return d.year === now.year &&
×
543
                    d.month === now.month;
544
            }
545
        }, {
546
            name: 'lastMonth',
547
            isUnary: true,
548
            iconName: 'filter_last_month',
549
            logic: (target: Date) => {
550
                if (!target) {
×
551
                    return false;
×
552
                }
553

554
                this.validateInputData(target);
×
555

556
                const d = IgxDateTimeFilteringOperand.getDateParts(target, 'yM');
×
557
                const now = IgxDateTimeFilteringOperand.getDateParts(new Date(), 'yM');
×
558
                if (!now.month) {
×
559
                    now.month = 11;
×
560
                    now.year -= 1;
×
561
                } else {
562
                    now.month--;
×
563
                }
564
                return d.year === now.year &&
×
565
                    d.month === now.month;
566
            }
567
        }, {
568
            name: 'nextMonth',
569
            isUnary: true,
570
            iconName: 'filter_next_month',
571
            logic: (target: Date) => {
572
                if (!target) {
×
573
                    return false;
×
574
                }
575

576
                this.validateInputData(target);
×
577

578
                const d = IgxDateTimeFilteringOperand.getDateParts(target, 'yM');
×
579
                const now = IgxDateTimeFilteringOperand.getDateParts(new Date(), 'yM');
×
580
                if (now.month === 11) {
×
581
                    now.month = 0;
×
582
                    now.year += 1;
×
583
                } else {
584
                    now.month++;
×
585
                }
586
                return d.year === now.year &&
×
587
                    d.month === now.month;
588
            }
589
        }, {
590
            name: 'thisYear',
591
            isUnary: true,
592
            iconName: 'filter_this_year',
593
            logic: (target: Date) => {
594
                if (!target) {
×
595
                    return false;
×
596
                }
597

598
                this.validateInputData(target);
×
599

600
                const d = IgxDateTimeFilteringOperand.getDateParts(target, 'y');
×
601
                const now = IgxDateTimeFilteringOperand.getDateParts(new Date(), 'y');
×
602
                return d.year === now.year;
×
603
            }
604
        }, {
605
            name: 'lastYear',
606
            isUnary: true,
607
            iconName: 'filter_last_year',
608
            logic: (target: Date) => {
609
                if (!target) {
×
610
                    return false;
×
611
                }
612

613
                this.validateInputData(target);
×
614

615
                const d = IgxDateTimeFilteringOperand.getDateParts(target, 'y');
×
616
                const now = IgxDateTimeFilteringOperand.getDateParts(new Date(), 'y');
×
617
                return d.year === now.year - 1;
×
618
            }
619
        }, {
620
            name: 'nextYear',
621
            isUnary: true,
622
            iconName: 'filter_next_year',
623
            logic: (target: Date) => {
624
                if (!target) {
×
625
                    return false;
×
626
                }
627

628
                this.validateInputData(target);
×
629

630
                const d = IgxDateTimeFilteringOperand.getDateParts(target, 'y');
×
631
                const now = IgxDateTimeFilteringOperand.getDateParts(new Date(), 'y');
×
632
                return d.year === now.year + 1;
×
633
            }
634
        }];
635
        
636
        this.operations = newOperations.concat(this.operations);
2✔
637
    }
638
}
639

640
/* blazorCSSuppress */
641
export class IgxTimeFilteringOperand extends IgxBaseDateTimeFilteringOperand {
642
    protected constructor() {
643
        super();
2✔
644
        const newOperations: IFilteringOperation[] = [{
2✔
645
            name: 'at',
646
            isUnary: false,
647
            iconName: 'filter_equal',
648
            logic: (target: Date, searchVal: Date) => {
649
                if (!target) {
9✔
650
                    return false;
2✔
651
                }
652
                this.validateInputData(target);
7✔
653
                const targetp = IgxTimeFilteringOperand.getDateParts(target, 'hms');
7✔
654
                const searchp = IgxTimeFilteringOperand.getDateParts(searchVal, 'hms');
7✔
655
                return targetp.hours === searchp.hours &&
7✔
656
                    targetp.minutes === searchp.minutes &&
657
                    targetp.seconds === searchp.seconds;
658
            }
659
        }, {
660
            name: 'not_at',
661
            isUnary: false,
662
            iconName: 'filter_not_equal',
663
            logic: (target: Date, searchVal: Date) => {
664
                if (!target) {
8✔
665
                    return true;
2✔
666
                }
667
                this.validateInputData(target);
6✔
668
                const targetp = IgxTimeFilteringOperand.getDateParts(target, 'hms');
6✔
669
                const searchp = IgxTimeFilteringOperand.getDateParts(searchVal, 'hms');
6✔
670
                return targetp.hours !== searchp.hours ||
6✔
671
                    targetp.minutes !== searchp.minutes ||
672
                    targetp.seconds !== searchp.seconds;
673
            }
674
        }, {
675
            name: 'before',
676
            isUnary: false,
677
            iconName: 'filter_before',
678
            logic: (target: Date, searchVal: Date) => {
679
                if (!target) {
8✔
680
                    return false;
2✔
681
                }
682

683
                this.validateInputData(target);
6✔
684
                const targetn = IgxTimeFilteringOperand.getDateParts(target, 'hms');
6✔
685
                const search = IgxTimeFilteringOperand.getDateParts(searchVal, 'hms');
6✔
686

687
                return targetn.hours < search.hours ? true : targetn.hours === search.hours && targetn.minutes < search.minutes ?
6✔
688
                    true : targetn.hours === search.hours && targetn.minutes === search.minutes && targetn.seconds < search.seconds;
4✔
689
            }
690
        }, {
691
            name: 'after',
692
            isUnary: false,
693
            iconName: 'filter_after',
694
            logic: (target: Date, searchVal: Date) => {
695
                if (!target) {
8✔
696
                    return false;
2✔
697
                }
698

699
                this.validateInputData(target);
6✔
700
                const targetn = IgxTimeFilteringOperand.getDateParts(target, 'hms');
6✔
701
                const search = IgxTimeFilteringOperand.getDateParts(searchVal, 'hms');
6✔
702

703
                return targetn.hours > search.hours ? true : targetn.hours === search.hours && targetn.minutes > search.minutes ?
6✔
704
                    true : targetn.hours === search.hours && targetn.minutes === search.minutes && targetn.seconds > search.seconds;
9✔
705
            }
706
        }, {
707
            name: 'at_before',
708
            isUnary: false,
709
            iconName: 'filter_before',
710
            logic: (target: Date, searchVal: Date) => {
711
                if (!target) {
8✔
712
                    return false;
2✔
713
                }
714

715
                this.validateInputData(target);
6✔
716
                const targetn = IgxTimeFilteringOperand.getDateParts(target, 'hms');
6✔
717
                const search = IgxTimeFilteringOperand.getDateParts(searchVal, 'hms');
6✔
718
                return (targetn.hours === search.hours && targetn.minutes === search.minutes && targetn.seconds === search.seconds) ||
6✔
719
                targetn.hours < search.hours ? true : targetn.hours === search.hours && targetn.minutes < search.minutes ?
11✔
720
                    true : targetn.hours === search.hours && targetn.minutes === search.minutes && targetn.seconds < search.seconds;
1!
721
            }
722
        }, {
723
            name: 'at_after',
724
            isUnary: false,
725
            iconName: 'filter_after',
726
            logic: (target: Date, searchVal: Date) => {
727
                if (!target) {
8✔
728
                    return false;
2✔
729
                }
730

731
                this.validateInputData(target);
6✔
732
                const targetn = IgxTimeFilteringOperand.getDateParts(target, 'hms');
6✔
733
                const search = IgxTimeFilteringOperand.getDateParts(searchVal, 'hms');
6✔
734
                return (targetn.hours === search.hours && targetn.minutes === search.minutes && targetn.seconds === search.seconds) ||
6✔
735
                    targetn.hours > search.hours ? true : targetn.hours === search.hours && targetn.minutes > search.minutes ?
11✔
736
                    true : targetn.hours === search.hours && targetn.minutes === search.minutes && targetn.seconds > search.seconds;
6✔
737
            }
738
        }];
739
        
740
        this.operations = newOperations.concat(this.operations);
2✔
741
    }
742

743
    /**
744
     * @hidden
745
     */
746
    public override findValueInSet(target: any, searchVal: Set<any>) {
747
        if (!target) {
×
748
            return false;
×
749
        }
750
        return searchVal.has(target.toLocaleTimeString());
×
751
    }
752
}
753

754
/* blazorCSSuppress */
755
/**
756
 * Provides filtering operations for numbers
757
 *
758
 * @export
759
 */
760
export class IgxNumberFilteringOperand extends IgxFilteringOperand {
761
    protected constructor() {
762
        super();
2✔
763
        const newOperations: IFilteringOperation[] = [{
2✔
764
            name: 'equals',
765
            isUnary: false,
766
            iconName: 'filter_equal',
767
            logic: (target: number, searchVal: number) => target === searchVal
1,207✔
768
        }, {
769
            name: 'doesNotEqual',
770
            isUnary: false,
771
            iconName: 'filter_not_equal',
772
            logic: (target: number, searchVal: number) => target !== searchVal
216✔
773
        }, {
774
            name: 'greaterThan',
775
            isUnary: false,
776
            iconName: 'filter_greater_than',
777
            logic: (target: number, searchVal: number) => target > searchVal
476✔
778
        }, {
779
            name: 'lessThan',
780
            isUnary: false,
781
            iconName: 'filter_less_than',
782
            logic: (target: number, searchVal: number) => target < searchVal
97✔
783
        }, {
784
            name: 'greaterThanOrEqualTo',
785
            isUnary: false,
786
            iconName: 'filter_greater_than_or_equal',
787
            logic: (target: number, searchVal: number) => target >= searchVal
100✔
788
        }, {
789
            name: 'lessThanOrEqualTo',
790
            isUnary: false,
791
            iconName: 'filter_less_than_or_equal',
792
            logic: (target: number, searchVal: number) => target <= searchVal
87✔
793
        }, {
794
            name: 'empty',
795
            isUnary: true,
796
            iconName: 'filter_empty',
797
            logic: (target: number) => target === null || target === undefined || isNaN(target)
18✔
798
        }, {
799
            name: 'notEmpty',
800
            isUnary: true,
801
            iconName: 'filter_not_empty',
802
            logic: (target: number) => target !== null && target !== undefined && !isNaN(target)
33✔
803
        }];
804
        
805
        this.operations = newOperations.concat(this.operations);
2✔
806
    }
807
}
808

809
/* blazorCSSuppress */
810
/**
811
 * Provides filtering operations for strings
812
 *
813
 * @export
814
 */
815
export class IgxStringFilteringOperand extends IgxFilteringOperand {
816
    protected constructor() {
817
        super();
2✔
818
        const newOperations: IFilteringOperation[] = [{
2✔
819
            name: 'contains',
820
            isUnary: false,
821
            iconName: 'filter_contains',
822
            logic: (target: string, searchVal: string, ignoreCase?: boolean) => {
823
                const search = IgxStringFilteringOperand.applyIgnoreCase(searchVal, ignoreCase);
2,435✔
824
                target = IgxStringFilteringOperand.applyIgnoreCase(target, ignoreCase);
2,435✔
825
                return target.indexOf(search) !== -1;
2,435✔
826
            }
827
        }, {
828
            name: 'doesNotContain',
829
            isUnary: false,
830
            iconName: 'filter_does_not_contain',
831
            logic: (target: string, searchVal: string, ignoreCase?: boolean) => {
832
                const search = IgxStringFilteringOperand.applyIgnoreCase(searchVal, ignoreCase);
23✔
833
                target = IgxStringFilteringOperand.applyIgnoreCase(target, ignoreCase);
23✔
834
                return target.indexOf(search) === -1;
23✔
835
            }
836
        }, {
837
            name: 'startsWith',
838
            isUnary: false,
839
            iconName: 'filter_starts_with',
840
            logic: (target: string, searchVal: string, ignoreCase?: boolean) => {
841
                const search = IgxStringFilteringOperand.applyIgnoreCase(searchVal, ignoreCase);
323✔
842
                target = IgxStringFilteringOperand.applyIgnoreCase(target, ignoreCase);
323✔
843
                return target.startsWith(search);
323✔
844
            }
845
        }, {
846
            name: 'endsWith',
847
            isUnary: false,
848
            iconName: 'filter_ends_with',
849
            logic: (target: string, searchVal: string, ignoreCase?: boolean) => {
850
                const search = IgxStringFilteringOperand.applyIgnoreCase(searchVal, ignoreCase);
44✔
851
                target = IgxStringFilteringOperand.applyIgnoreCase(target, ignoreCase);
44✔
852
                return target.endsWith(search);
44✔
853
            }
854
        }, {
855
            name: 'equals',
856
            isUnary: false,
857
            iconName: 'filter_equal',
858
            logic: (target: string, searchVal: string, ignoreCase?: boolean) => {
859
                const search = IgxStringFilteringOperand.applyIgnoreCase(searchVal, ignoreCase);
366✔
860
                target = IgxStringFilteringOperand.applyIgnoreCase(target, ignoreCase);
366✔
861
                return target === search;
366✔
862
            }
863
        }, {
864
            name: 'doesNotEqual',
865
            isUnary: false,
866
            iconName: 'filter_not_equal',
867
            logic: (target: string, searchVal: string, ignoreCase?: boolean) => {
868
                const search = IgxStringFilteringOperand.applyIgnoreCase(searchVal, ignoreCase);
18✔
869
                target = IgxStringFilteringOperand.applyIgnoreCase(target, ignoreCase);
18✔
870
                return target !== search;
18✔
871
            }
872
        }, {
873
            name: 'empty',
874
            isUnary: true,
875
            iconName: 'filter_empty',
876
            logic: (target: string) => target === null || target === undefined || target.length === 0
57✔
877
        }, {
878
            name: 'notEmpty',
879
            isUnary: true,
880
            iconName: 'filter_not_empty',
881
            logic: (target: string) => target !== null && target !== undefined && target.length > 0
11✔
882
        }];
883
        
884
        this.operations = newOperations.concat(this.operations);
2✔
885
    }
886

887
    /**
888
     * Applies case sensitivity on strings if provided
889
     *
890
     * @memberof IgxStringFilteringOperand
891
     */
892
    public static applyIgnoreCase(a: string, ignoreCase: boolean): string {
893
        a = a ?? '';
6,418✔
894
        // bulletproof
895
        return ignoreCase ? ('' + a).toLowerCase() : a;
6,418✔
896
    }
897
}
898

899
/* tsPlainInterface */
900
/* marshalByValue */
901
/**
902
 * Interface describing filtering operations
903
 *
904
 * @export
905
 */
906
export interface IFilteringOperation {
907
    name: string;
908
    isUnary: boolean;
909
    isNestedQuery?: boolean;
910
    iconName: string;
911
    hidden?: boolean;
912
    /* blazorCSSuppress */
913
    /* blazorAlternateType: FilteringOperationLogicHandler */
914
    logic: (value: any, searchVal?: any, ignoreCase?: boolean) => boolean;
915
}
916

917
/**
918
 * Interface describing Date object in parts
919
 *
920
 * @export
921
 */
922
export interface IDateParts {
923
    year: number;
924
    month: number;
925
    day: number;
926
    hours: number;
927
    minutes: number;
928
    seconds: number;
929
    milliseconds: number;
930
}
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

© 2025 Coveralls, Inc