1
- import { Component , Input , ViewChild , ChangeDetectorRef , ViewChildren , QueryList , ElementRef } from '@angular/core' ;
2
- import { PositionSettings , VerticalAlignment , HorizontalAlignment , OverlaySettings , Point } from '../../../services/overlay/utilities' ;
1
+ import {
2
+ Component , Input , ViewChild , ChangeDetectorRef , ViewChildren , QueryList , ElementRef , AfterViewInit , OnDestroy
3
+ } from '@angular/core' ;
4
+ import { VerticalAlignment , HorizontalAlignment , Point } from '../../../services/overlay/utilities' ;
3
5
import { ConnectedPositioningStrategy } from '../../../services/overlay/position/connected-positioning-strategy' ;
4
6
import { IgxFilteringService } from '../grid-filtering.service' ;
5
7
import { IgxOverlayService } from '../../../services/overlay/overlay' ;
6
- import { DisplayDensity } from '../../../core/displayDensity' ;
7
- import { IgxToggleDirective , CloseScrollStrategy } from 'igniteui-angular' ;
8
+ import { IgxToggleDirective , CloseScrollStrategy , IButtonGroupEventArgs } from 'igniteui-angular' ;
8
9
import { IgxGridBaseComponent , IgxColumnComponent } from '../../grid' ;
9
10
import { FilteringExpressionsTree , IFilteringExpressionsTree } from '../../../data-operations/filtering-expressions-tree' ;
10
11
import { FilteringLogic , IFilteringExpression } from '../../../data-operations/filtering-expression.interface' ;
11
12
import { IgxStringFilteringOperand } from '../../../data-operations/filtering-condition' ;
12
13
import { IgxChipComponent } from '../../../chips' ;
13
14
import { IgxSelectComponent } from '../../../select' ;
15
+ import { takeUntil } from 'rxjs/operators' ;
16
+ import { Subject } from 'rxjs' ;
14
17
15
18
class ExpressionItem {
16
19
constructor ( parent ?: ExpressionGroupItem ) {
@@ -46,7 +49,7 @@ class ExpressionOperandItem extends ExpressionItem {
46
49
selector : 'igx-advanced-filtering-dialog' ,
47
50
templateUrl : './advanced-filtering-dialog.component.html'
48
51
} )
49
- export class IgxAdvancedFilteringDialogComponent {
52
+ export class IgxAdvancedFilteringDialogComponent implements AfterViewInit , OnDestroy {
50
53
@Input ( )
51
54
public filteringService : IgxFilteringService ;
52
55
@@ -68,6 +71,10 @@ export class IgxAdvancedFilteringDialogComponent {
68
71
69
72
public addModeExpression : ExpressionOperandItem ;
70
73
74
+ public contextualGroup : ExpressionGroupItem ;
75
+
76
+ public filteringLogics ;
77
+
71
78
public selectedCondition : string ;
72
79
public searchValue : string ;
73
80
@@ -97,13 +104,25 @@ export class IgxAdvancedFilteringDialogComponent {
97
104
@ViewChildren ( IgxChipComponent )
98
105
public chips : QueryList < IgxChipComponent > ;
99
106
107
+ private destroy$ = new Subject < any > ( ) ;
100
108
private _selectedColumn : IgxColumnComponent ;
101
109
private _clickTimer ;
102
110
private _dblClickDelay = 200 ;
103
111
private _preventChipClick = false ;
104
112
105
113
constructor ( public cdr : ChangeDetectorRef ) { }
106
114
115
+ public ngAfterViewInit ( ) : void {
116
+ this . contextMenuToggle . onClosed . pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( args ) => {
117
+ this . contextualGroup = null ;
118
+ } ) ;
119
+ }
120
+
121
+ public ngOnDestroy ( ) : void {
122
+ this . destroy$ . next ( true ) ;
123
+ this . destroy$ . complete ( ) ;
124
+ }
125
+
107
126
public get displayDensity ( ) {
108
127
return this . grid . displayDensity ;
109
128
}
@@ -271,7 +290,7 @@ export class IgxAdvancedFilteringDialogComponent {
271
290
public onChipClick ( expressionItem : ExpressionOperandItem ) {
272
291
this . _clickTimer = setTimeout ( ( ) => {
273
292
if ( ! this . _preventChipClick ) {
274
- this . toggleExpression ( expressionItem ) ;
293
+ this . onToggleExpression ( expressionItem ) ;
275
294
}
276
295
this . _preventChipClick = false ;
277
296
} , this . _dblClickDelay ) ;
@@ -311,6 +330,11 @@ export class IgxAdvancedFilteringDialogComponent {
311
330
}
312
331
313
332
private clearSelection ( ) {
333
+ for ( const group of this . selectedGroups ) {
334
+ group . selected = false ;
335
+ }
336
+ this . selectedGroups = [ ] ;
337
+
314
338
for ( const expr of this . selectedExpressions ) {
315
339
expr . selected = false ;
316
340
}
@@ -325,22 +349,44 @@ export class IgxAdvancedFilteringDialogComponent {
325
349
this . toggleExpression ( expressionItem ) ;
326
350
}
327
351
328
- private toggleExpression ( expressionItem : ExpressionOperandItem ) {
352
+ private onToggleExpression ( expressionItem : ExpressionOperandItem ) {
329
353
this . exitOperandEdit ( ) ;
354
+ this . toggleExpression ( expressionItem ) ;
355
+
356
+ this . toggleContextMenu ( ) ;
357
+ }
358
+
359
+ private toggleExpression ( expressionItem : ExpressionOperandItem ) {
330
360
expressionItem . selected = ! expressionItem . selected ;
331
361
332
362
if ( expressionItem . selected ) {
333
363
this . selectedExpressions . push ( expressionItem ) ;
334
364
} else {
335
365
const index = this . selectedExpressions . indexOf ( expressionItem ) ;
336
366
this . selectedExpressions . splice ( index , 1 ) ;
367
+ this . deselectParentRecursive ( expressionItem ) ;
337
368
}
338
-
339
- this . toggleContextMenu ( ) ;
340
369
}
341
370
342
371
private toggleContextMenu ( ) {
343
- if ( this . selectedExpressions . length > 1 ) {
372
+ const contextualGroup = this . findSingleSelectedGroup ( ) ;
373
+
374
+ if ( contextualGroup || this . selectedExpressions . length > 1 ) {
375
+ this . contextualGroup = contextualGroup ;
376
+
377
+ if ( contextualGroup ) {
378
+ this . filteringLogics = [
379
+ {
380
+ label : this . grid . resourceStrings . igx_grid_filter_operator_and ,
381
+ selected : contextualGroup . operator === FilteringLogic . And
382
+ } ,
383
+ {
384
+ label : this . grid . resourceStrings . igx_grid_filter_operator_or ,
385
+ selected : contextualGroup . operator === FilteringLogic . Or
386
+ }
387
+ ] ;
388
+ }
389
+
344
390
setTimeout ( ( ) => {
345
391
const chips = this . chips . filter ( c => this . selectedExpressions . includes ( c . data ) ) ;
346
392
const minTop = chips . reduce ( ( t , c ) =>
@@ -350,16 +396,40 @@ export class IgxAdvancedFilteringDialogComponent {
350
396
this . _overlaySettings . positionStrategy . settings . target = new Point ( maxRight , minTop ) ;
351
397
352
398
if ( this . contextMenuToggle . collapsed ) {
353
- this . contextMenuToggle . open ( this . _overlaySettings ) ;
399
+ this . contextMenuToggle . open ( this . _overlaySettings ) ;
354
400
} else {
355
- this . contextMenuToggle . reposition ( ) ;
401
+ this . contextMenuToggle . reposition ( ) ;
356
402
}
357
403
} , 200 ) ;
358
404
} else {
359
405
this . contextMenuToggle . close ( ) ;
360
406
}
361
407
}
362
408
409
+ private findSingleSelectedGroup ( ) : ExpressionGroupItem {
410
+ for ( const group of this . selectedGroups ) {
411
+ const containsAllSelectedExpressions = this . selectedExpressions . every ( op => this . isInsideGroup ( op , group ) ) ;
412
+
413
+ if ( containsAllSelectedExpressions ) {
414
+ return group ;
415
+ }
416
+ }
417
+
418
+ return null ;
419
+ }
420
+
421
+ private isInsideGroup ( item : ExpressionItem , group : ExpressionGroupItem ) : boolean {
422
+ if ( ! item ) {
423
+ return false ;
424
+ }
425
+
426
+ if ( item . parent === group ) {
427
+ return true ;
428
+ }
429
+
430
+ return this . isInsideGroup ( item . parent , group ) ;
431
+ }
432
+
363
433
private deleteItem ( expressionItem : ExpressionItem ) {
364
434
if ( ! expressionItem . parent ) {
365
435
this . rootGroup = null ;
@@ -420,45 +490,51 @@ export class IgxAdvancedFilteringDialogComponent {
420
490
421
491
private toggleGroup ( groupItem : ExpressionGroupItem ) {
422
492
this . exitOperandEdit ( ) ;
423
- groupItem . selected = ! groupItem . selected ;
424
-
425
- if ( groupItem . selected ) {
426
- this . selectedGroups . push ( groupItem ) ;
427
- } else {
428
- const index = this . selectedGroups . indexOf ( groupItem ) ;
429
- this . selectedGroups . splice ( index , 1 ) ;
493
+ this . toggleGroupRecursive ( groupItem , ! groupItem . selected ) ;
494
+ if ( ! groupItem . selected ) {
495
+ this . deselectParentRecursive ( groupItem ) ;
430
496
}
497
+ this . toggleContextMenu ( ) ;
498
+ }
431
499
432
- this . clearSelection ( ) ;
500
+ private toggleGroupRecursive ( groupItem : ExpressionGroupItem , selected : boolean ) {
501
+ if ( groupItem . selected !== selected ) {
502
+ groupItem . selected = selected ;
433
503
434
- for ( const group of this . selectedGroups ) {
435
- this . selectGroupRecursive ( group ) ;
504
+ if ( groupItem . selected ) {
505
+ this . selectedGroups . push ( groupItem ) ;
506
+ } else {
507
+ const index = this . selectedGroups . indexOf ( groupItem ) ;
508
+ this . selectedGroups . splice ( index , 1 ) ;
509
+ }
436
510
}
437
511
438
- this . toggleContextMenu ( ) ;
439
- }
440
-
441
- private selectGroupRecursive ( group : ExpressionGroupItem ) {
442
- for ( const expr of group . children ) {
512
+ for ( const expr of groupItem . children ) {
443
513
if ( expr instanceof ExpressionGroupItem ) {
444
- if ( ! expr . selected ) {
445
- expr . selected = true ;
446
- }
447
- if ( ! this . selectedGroups . includes ( expr ) ) {
448
- this . selectedGroups . push ( expr ) ;
449
- }
450
- this . selectGroupRecursive ( expr ) ;
514
+ this . toggleGroupRecursive ( expr , selected ) ;
451
515
} else {
452
- const operandItem = expr as ExpressionOperandItem ;
453
- if ( ! operandItem . selected ) {
454
- this . toggleExpression ( operandItem ) ;
516
+ const operandExpression = expr as ExpressionOperandItem ;
517
+ if ( operandExpression . selected !== selected ) {
518
+ this . toggleExpression ( operandExpression ) ;
455
519
}
456
520
}
457
521
}
458
522
}
459
523
524
+ private deselectParentRecursive ( expressionItem : ExpressionItem ) {
525
+ const parent = expressionItem . parent ;
526
+ if ( parent ) {
527
+ if ( parent . selected ) {
528
+ parent . selected = false ;
529
+ const index = this . selectedGroups . indexOf ( parent ) ;
530
+ this . selectedGroups . splice ( index , 1 ) ;
531
+ }
532
+ this . deselectParentRecursive ( parent ) ;
533
+ }
534
+ }
535
+
460
536
public ungroup ( ) {
461
- const selectedGroup = this . selectedGroups [ 0 ] ;
537
+ const selectedGroup = this . contextualGroup ;
462
538
const parent = selectedGroup . parent ;
463
539
if ( parent ) {
464
540
const index = parent . children . indexOf ( selectedGroup ) ;
@@ -469,25 +545,24 @@ export class IgxAdvancedFilteringDialogComponent {
469
545
}
470
546
}
471
547
472
- this . selectedGroups = [ ] ;
473
548
this . clearSelection ( ) ;
474
- this . toggleContextMenu ( ) ;
475
549
}
476
550
477
551
public deleteGroup ( ) {
478
- const selectedGroup = this . selectedGroups [ 0 ] ;
552
+ const selectedGroup = this . contextualGroup ;
479
553
const parent = selectedGroup . parent ;
480
554
if ( parent ) {
481
555
const index = parent . children . indexOf ( selectedGroup ) ;
482
556
parent . children . splice ( index , 1 ) ;
557
+ } else {
558
+ this . rootGroup = null ;
483
559
}
484
- this . selectedGroups = [ ] ;
560
+
485
561
this . clearSelection ( ) ;
486
- this . toggleContextMenu ( ) ;
487
562
}
488
563
489
- public onLogicOperatorButtonClicked ( operator : FilteringLogic ) {
490
- this . selectedGroups [ 0 ] . operator = operator ;
564
+ public selectFilteringLogic ( event : IButtonGroupEventArgs ) {
565
+ this . contextualGroup . operator = event . index as FilteringLogic ;
491
566
}
492
567
493
568
public initialize ( filteringService : IgxFilteringService , overlayService : IgxOverlayService ,
0 commit comments