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' ;
35import { ConnectedPositioningStrategy } from '../../../services/overlay/position/connected-positioning-strategy' ;
46import { IgxFilteringService } from '../grid-filtering.service' ;
57import { 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' ;
89import { IgxGridBaseComponent , IgxColumnComponent } from '../../grid' ;
910import { FilteringExpressionsTree , IFilteringExpressionsTree } from '../../../data-operations/filtering-expressions-tree' ;
1011import { FilteringLogic , IFilteringExpression } from '../../../data-operations/filtering-expression.interface' ;
1112import { IgxStringFilteringOperand } from '../../../data-operations/filtering-condition' ;
1213import { IgxChipComponent } from '../../../chips' ;
1314import { IgxSelectComponent } from '../../../select' ;
15+ import { takeUntil } from 'rxjs/operators' ;
16+ import { Subject } from 'rxjs' ;
1417
1518class ExpressionItem {
1619 constructor ( parent ?: ExpressionGroupItem ) {
@@ -46,7 +49,7 @@ class ExpressionOperandItem extends ExpressionItem {
4649 selector : 'igx-advanced-filtering-dialog' ,
4750 templateUrl : './advanced-filtering-dialog.component.html'
4851} )
49- export class IgxAdvancedFilteringDialogComponent {
52+ export class IgxAdvancedFilteringDialogComponent implements AfterViewInit , OnDestroy {
5053 @Input ( )
5154 public filteringService : IgxFilteringService ;
5255
@@ -68,6 +71,10 @@ export class IgxAdvancedFilteringDialogComponent {
6871
6972 public addModeExpression : ExpressionOperandItem ;
7073
74+ public contextualGroup : ExpressionGroupItem ;
75+
76+ public filteringLogics ;
77+
7178 public selectedCondition : string ;
7279 public searchValue : string ;
7380
@@ -97,13 +104,25 @@ export class IgxAdvancedFilteringDialogComponent {
97104 @ViewChildren ( IgxChipComponent )
98105 public chips : QueryList < IgxChipComponent > ;
99106
107+ private destroy$ = new Subject < any > ( ) ;
100108 private _selectedColumn : IgxColumnComponent ;
101109 private _clickTimer ;
102110 private _dblClickDelay = 200 ;
103111 private _preventChipClick = false ;
104112
105113 constructor ( public cdr : ChangeDetectorRef ) { }
106114
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+
107126 public get displayDensity ( ) {
108127 return this . grid . displayDensity ;
109128 }
@@ -271,7 +290,7 @@ export class IgxAdvancedFilteringDialogComponent {
271290 public onChipClick ( expressionItem : ExpressionOperandItem ) {
272291 this . _clickTimer = setTimeout ( ( ) => {
273292 if ( ! this . _preventChipClick ) {
274- this . toggleExpression ( expressionItem ) ;
293+ this . onToggleExpression ( expressionItem ) ;
275294 }
276295 this . _preventChipClick = false ;
277296 } , this . _dblClickDelay ) ;
@@ -311,6 +330,11 @@ export class IgxAdvancedFilteringDialogComponent {
311330 }
312331
313332 private clearSelection ( ) {
333+ for ( const group of this . selectedGroups ) {
334+ group . selected = false ;
335+ }
336+ this . selectedGroups = [ ] ;
337+
314338 for ( const expr of this . selectedExpressions ) {
315339 expr . selected = false ;
316340 }
@@ -325,22 +349,44 @@ export class IgxAdvancedFilteringDialogComponent {
325349 this . toggleExpression ( expressionItem ) ;
326350 }
327351
328- private toggleExpression ( expressionItem : ExpressionOperandItem ) {
352+ private onToggleExpression ( expressionItem : ExpressionOperandItem ) {
329353 this . exitOperandEdit ( ) ;
354+ this . toggleExpression ( expressionItem ) ;
355+
356+ this . toggleContextMenu ( ) ;
357+ }
358+
359+ private toggleExpression ( expressionItem : ExpressionOperandItem ) {
330360 expressionItem . selected = ! expressionItem . selected ;
331361
332362 if ( expressionItem . selected ) {
333363 this . selectedExpressions . push ( expressionItem ) ;
334364 } else {
335365 const index = this . selectedExpressions . indexOf ( expressionItem ) ;
336366 this . selectedExpressions . splice ( index , 1 ) ;
367+ this . deselectParentRecursive ( expressionItem ) ;
337368 }
338-
339- this . toggleContextMenu ( ) ;
340369 }
341370
342371 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+
344390 setTimeout ( ( ) => {
345391 const chips = this . chips . filter ( c => this . selectedExpressions . includes ( c . data ) ) ;
346392 const minTop = chips . reduce ( ( t , c ) =>
@@ -350,16 +396,40 @@ export class IgxAdvancedFilteringDialogComponent {
350396 this . _overlaySettings . positionStrategy . settings . target = new Point ( maxRight , minTop ) ;
351397
352398 if ( this . contextMenuToggle . collapsed ) {
353- this . contextMenuToggle . open ( this . _overlaySettings ) ;
399+ this . contextMenuToggle . open ( this . _overlaySettings ) ;
354400 } else {
355- this . contextMenuToggle . reposition ( ) ;
401+ this . contextMenuToggle . reposition ( ) ;
356402 }
357403 } , 200 ) ;
358404 } else {
359405 this . contextMenuToggle . close ( ) ;
360406 }
361407 }
362408
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+
363433 private deleteItem ( expressionItem : ExpressionItem ) {
364434 if ( ! expressionItem . parent ) {
365435 this . rootGroup = null ;
@@ -420,45 +490,51 @@ export class IgxAdvancedFilteringDialogComponent {
420490
421491 private toggleGroup ( groupItem : ExpressionGroupItem ) {
422492 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 ) ;
430496 }
497+ this . toggleContextMenu ( ) ;
498+ }
431499
432- this . clearSelection ( ) ;
500+ private toggleGroupRecursive ( groupItem : ExpressionGroupItem , selected : boolean ) {
501+ if ( groupItem . selected !== selected ) {
502+ groupItem . selected = selected ;
433503
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+ }
436510 }
437511
438- this . toggleContextMenu ( ) ;
439- }
440-
441- private selectGroupRecursive ( group : ExpressionGroupItem ) {
442- for ( const expr of group . children ) {
512+ for ( const expr of groupItem . children ) {
443513 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 ) ;
451515 } 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 ) ;
455519 }
456520 }
457521 }
458522 }
459523
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+
460536 public ungroup ( ) {
461- const selectedGroup = this . selectedGroups [ 0 ] ;
537+ const selectedGroup = this . contextualGroup ;
462538 const parent = selectedGroup . parent ;
463539 if ( parent ) {
464540 const index = parent . children . indexOf ( selectedGroup ) ;
@@ -469,25 +545,24 @@ export class IgxAdvancedFilteringDialogComponent {
469545 }
470546 }
471547
472- this . selectedGroups = [ ] ;
473548 this . clearSelection ( ) ;
474- this . toggleContextMenu ( ) ;
475549 }
476550
477551 public deleteGroup ( ) {
478- const selectedGroup = this . selectedGroups [ 0 ] ;
552+ const selectedGroup = this . contextualGroup ;
479553 const parent = selectedGroup . parent ;
480554 if ( parent ) {
481555 const index = parent . children . indexOf ( selectedGroup ) ;
482556 parent . children . splice ( index , 1 ) ;
557+ } else {
558+ this . rootGroup = null ;
483559 }
484- this . selectedGroups = [ ] ;
560+
485561 this . clearSelection ( ) ;
486- this . toggleContextMenu ( ) ;
487562 }
488563
489- public onLogicOperatorButtonClicked ( operator : FilteringLogic ) {
490- this . selectedGroups [ 0 ] . operator = operator ;
564+ public selectFilteringLogic ( event : IButtonGroupEventArgs ) {
565+ this . contextualGroup . operator = event . index as FilteringLogic ;
491566 }
492567
493568 public initialize ( filteringService : IgxFilteringService , overlayService : IgxOverlayService ,
0 commit comments