1
- import { Component , AfterViewInit , Input , ViewChild , ChangeDetectorRef , ChangeDetectionStrategy } from '@angular/core' ;
2
- import { PositionSettings , VerticalAlignment , HorizontalAlignment , OverlaySettings } from '../../../services/overlay/utilities' ;
1
+ import { Component , Input , ViewChild , ChangeDetectorRef , ViewChildren , QueryList } from '@angular/core' ;
2
+ import { PositionSettings , VerticalAlignment , HorizontalAlignment , OverlaySettings , Point } from '../../../services/overlay/utilities' ;
3
3
import { ConnectedPositioningStrategy } from '../../../services/overlay/position/connected-positioning-strategy' ;
4
- import { AbsoluteScrollStrategy } from '../../../services/overlay/scroll/absolute-scroll-strategy' ;
5
4
import { IgxFilteringService } from '../grid-filtering.service' ;
6
5
import { IgxOverlayService } from '../../../services/overlay/overlay' ;
7
6
import { DisplayDensity } from '../../../core/displayDensity' ;
8
- import { IgxToggleDirective } from 'igniteui-angular' ;
7
+ import { IgxToggleDirective , CloseScrollStrategy } from 'igniteui-angular' ;
9
8
import { IgxGridBaseComponent , IgxColumnComponent } from '../../grid' ;
10
9
import { FilteringExpressionsTree , IFilteringExpressionsTree } from '../../../data-operations/filtering-expressions-tree' ;
11
10
import { FilteringLogic , IFilteringExpression } from '../../../data-operations/filtering-expression.interface' ;
12
11
import { IgxStringFilteringOperand } from '../../../data-operations/filtering-condition' ;
12
+ import { IgxChipComponent } from '../../../chips' ;
13
13
14
14
class ExpressionItem {
15
15
constructor ( parent ?: ExpressionGroupItem ) {
@@ -60,17 +60,38 @@ export class IgxAdvancedFilteringDialogComponent {
60
60
61
61
public rootGroup : ExpressionGroupItem ;
62
62
63
- public selectedExpressions : ExpressionItem [ ] = [ ] ;
63
+ public selectedExpressions : ExpressionOperandItem [ ] = [ ] ;
64
+
65
+ public selectedGroups : ExpressionGroupItem [ ] = [ ] ;
64
66
65
67
public currentGroup : ExpressionGroupItem ;
66
68
67
69
public editedExpression : ExpressionOperandItem ;
68
70
69
71
public addModeExpression : ExpressionOperandItem ;
70
72
73
+ public selectedGroup : ExpressionGroupItem ;
74
+
71
75
public selectedCondition : string ;
72
76
public searchValue : string ;
73
77
78
+ public _positionSettings = {
79
+ horizontalStartPoint : HorizontalAlignment . Right ,
80
+ verticalStartPoint : VerticalAlignment . Top
81
+ } ;
82
+ public _overlaySettings = {
83
+ closeOnOutsideClick : false ,
84
+ modal : false ,
85
+ positionStrategy : new ConnectedPositioningStrategy ( this . _positionSettings ) ,
86
+ scrollStrategy : new CloseScrollStrategy ( )
87
+ } ;
88
+
89
+ @ViewChild ( IgxToggleDirective , { static : true } )
90
+ public contextMenuToggle : IgxToggleDirective ;
91
+
92
+ @ViewChildren ( IgxChipComponent )
93
+ public chips : QueryList < IgxChipComponent > ;
94
+
74
95
private _selectedColumn : IgxColumnComponent ;
75
96
private _clickTimer ;
76
97
private _dblClickDelay = 200 ;
@@ -214,7 +235,7 @@ export class IgxAdvancedFilteringDialogComponent {
214
235
this . deleteItem ( expressionItem ) ;
215
236
}
216
237
217
- public onChipClick ( expressionItem : ExpressionItem ) {
238
+ public onChipClick ( expressionItem : ExpressionOperandItem ) {
218
239
this . _clickTimer = setTimeout ( ( ) => {
219
240
if ( ! this . _preventChipClick ) {
220
241
this . toggleExpression ( expressionItem ) ;
@@ -230,10 +251,7 @@ export class IgxAdvancedFilteringDialogComponent {
230
251
}
231
252
232
253
public enterExpressionEdit ( expressionItem : ExpressionOperandItem ) {
233
- for ( const expr of this . selectedExpressions ) {
234
- expr . selected = false ;
235
- }
236
- this . selectedExpressions = [ ] ;
254
+ this . clearSelection ( ) ;
237
255
238
256
if ( this . editedExpression ) {
239
257
this . editedExpression . inEditMode = false ;
@@ -249,13 +267,22 @@ export class IgxAdvancedFilteringDialogComponent {
249
267
this . editedExpression = expressionItem ;
250
268
}
251
269
270
+ private clearSelection ( ) {
271
+ for ( const expr of this . selectedExpressions ) {
272
+ expr . selected = false ;
273
+ }
274
+ this . selectedExpressions = [ ] ;
275
+
276
+ this . toggleContextMenu ( ) ;
277
+ }
278
+
252
279
public enterExpressionAdd ( expressionItem : ExpressionOperandItem ) {
253
280
expressionItem . inAddMode = true ;
254
281
this . addModeExpression = expressionItem ;
255
282
this . toggleExpression ( expressionItem ) ;
256
283
}
257
284
258
- private toggleExpression ( expressionItem : ExpressionItem ) {
285
+ private toggleExpression ( expressionItem : ExpressionOperandItem ) {
259
286
expressionItem . selected = ! expressionItem . selected ;
260
287
261
288
if ( expressionItem . selected ) {
@@ -264,6 +291,29 @@ export class IgxAdvancedFilteringDialogComponent {
264
291
const index = this . selectedExpressions . indexOf ( expressionItem ) ;
265
292
this . selectedExpressions . splice ( index , 1 ) ;
266
293
}
294
+
295
+ this . toggleContextMenu ( ) ;
296
+ }
297
+
298
+ private toggleContextMenu ( ) {
299
+ if ( this . selectedExpressions . length > 1 ) {
300
+ setTimeout ( ( ) => {
301
+ const chips = this . chips . filter ( c => this . selectedExpressions . includes ( c . data ) ) ;
302
+ const minTop = chips . reduce ( ( t , c ) =>
303
+ Math . min ( t , c . elementRef . nativeElement . getBoundingClientRect ( ) . top ) , Number . MAX_VALUE ) ;
304
+ const maxRight = chips . reduce ( ( r , c ) =>
305
+ Math . max ( r , c . elementRef . nativeElement . getBoundingClientRect ( ) . right ) , 0 ) ;
306
+ this . _overlaySettings . positionStrategy . settings . target = new Point ( maxRight , minTop ) ;
307
+
308
+ if ( this . contextMenuToggle . collapsed ) {
309
+ this . contextMenuToggle . open ( this . _overlaySettings ) ;
310
+ } else {
311
+ this . contextMenuToggle . reposition ( ) ;
312
+ }
313
+ } , 200 ) ;
314
+ } else {
315
+ this . contextMenuToggle . close ( ) ;
316
+ }
267
317
}
268
318
269
319
private deleteItem ( expressionItem : ExpressionItem ) {
@@ -284,6 +334,113 @@ export class IgxAdvancedFilteringDialogComponent {
284
334
eventArgs . stopPropagation ( ) ;
285
335
}
286
336
337
+ public createAndGroup ( ) {
338
+ this . createGroup ( FilteringLogic . And ) ;
339
+ }
340
+
341
+ public createOrGroup ( ) {
342
+ this . createGroup ( FilteringLogic . Or ) ;
343
+ }
344
+
345
+ private createGroup ( operator : FilteringLogic ) {
346
+ const chips = this . chips . toArray ( ) ;
347
+ const minIndex = this . selectedExpressions . reduce ( ( i , e ) => Math . min ( i , chips . findIndex ( c => c . data === e ) ) , Number . MAX_VALUE ) ;
348
+ const firstExpression = chips [ minIndex ] . data ;
349
+
350
+ const parent = firstExpression . parent ;
351
+ const groupItem = new ExpressionGroupItem ( operator , parent ) ;
352
+
353
+ const index = parent . children . indexOf ( firstExpression ) ;
354
+ parent . children . splice ( index , 0 , groupItem ) ;
355
+
356
+ for ( const expr of this . selectedExpressions ) {
357
+ this . deleteItem ( expr ) ;
358
+ groupItem . children . push ( expr ) ;
359
+ expr . parent = groupItem ;
360
+ }
361
+
362
+ this . clearSelection ( ) ;
363
+ }
364
+
365
+ public deleteFilters ( ) {
366
+ for ( const expr of this . selectedExpressions ) {
367
+ this . deleteItem ( expr ) ;
368
+ }
369
+
370
+ this . clearSelection ( ) ;
371
+ }
372
+
373
+ public onGroupClick ( groupItem : ExpressionGroupItem ) {
374
+ this . toggleGroup ( groupItem ) ;
375
+ }
376
+
377
+ private toggleGroup ( groupItem : ExpressionGroupItem ) {
378
+ groupItem . selected = ! groupItem . selected ;
379
+
380
+ if ( groupItem . selected ) {
381
+ this . selectedGroups . push ( groupItem ) ;
382
+ } else {
383
+ const index = this . selectedGroups . indexOf ( groupItem ) ;
384
+ this . selectedGroups . splice ( index , 1 ) ;
385
+ }
386
+
387
+ this . clearSelection ( ) ;
388
+
389
+ for ( const group of this . selectedGroups ) {
390
+ this . selectGroupRecursive ( group ) ;
391
+ }
392
+
393
+ this . toggleContextMenu ( ) ;
394
+ }
395
+
396
+ private selectGroupRecursive ( group : ExpressionGroupItem ) {
397
+ for ( const expr of group . children ) {
398
+ if ( expr instanceof ExpressionGroupItem ) {
399
+ if ( ! expr . selected ) {
400
+ expr . selected = true ;
401
+ }
402
+ if ( ! this . selectedGroups . includes ( expr ) ) {
403
+ this . selectedGroups . push ( expr ) ;
404
+ }
405
+ this . selectGroupRecursive ( expr ) ;
406
+ } else {
407
+ const operandItem = expr as ExpressionOperandItem ;
408
+ if ( ! operandItem . selected ) {
409
+ this . toggleExpression ( operandItem ) ;
410
+ }
411
+ }
412
+ }
413
+ }
414
+
415
+ public ungroup ( ) {
416
+ const parent = this . selectedGroup . parent ;
417
+ if ( parent ) {
418
+ const index = parent . children . indexOf ( this . selectedGroup ) ;
419
+ parent . children . splice ( index , 1 , ...this . selectedGroup . children ) ;
420
+
421
+ for ( const expr of this . selectedGroup . children ) {
422
+ expr . parent = parent ;
423
+ }
424
+ }
425
+
426
+ this . selectedGroup = null ;
427
+ this . toggleContextMenu ( ) ;
428
+ }
429
+
430
+ public deleteGroup ( ) {
431
+ const parent = this . selectedGroup . parent ;
432
+ if ( parent ) {
433
+ const index = parent . children . indexOf ( this . selectedGroup ) ;
434
+ parent . children . splice ( index , 1 ) ;
435
+ }
436
+ this . selectedGroup = null ;
437
+ this . toggleContextMenu ( ) ;
438
+ }
439
+
440
+ public onLogicOperatorButtonClicked ( operator : FilteringLogic ) {
441
+ this . selectedGroups [ 0 ] . operator = operator ;
442
+ }
443
+
287
444
public initialize ( filteringService : IgxFilteringService , overlayService : IgxOverlayService ,
288
445
overlayComponentId : string ) {
289
446
this . filteringService = filteringService ;
0 commit comments