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

IgniteUI / igniteui-angular / 23493206253

24 Mar 2026 01:55PM UTC coverage: 89.24% (-0.06%) from 89.304%
23493206253

push

github

web-flow
feat(extras): add igniteui-angular-extras library to monorepo (#16932)

14652 of 17256 branches covered (84.91%)

Branch coverage included in aggregate %.

587 of 672 new or added lines in 10 files covered. (87.35%)

29655 of 32393 relevant lines covered (91.55%)

33772.23 hits per line

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

78.43
/projects/igniteui-angular-extras/src/lib/context-menu/context-menu.component.ts
1
import { AfterViewInit, Component, ElementRef, ViewChild, ViewContainerRef, OnDestroy, CUSTOM_ELEMENTS_SCHEMA, inject } from '@angular/core';
2
import { CommonModule } from '@angular/common';
3
import { Subject } from 'rxjs';
4
import { takeUntil } from 'rxjs/operators';
5
import {
6
    IgxBarSeriesModule, IgxCategoryChartModule, IgxCategoryXAxisModule,
7
    IgxDataChartCategoryModule, IgxDataChartCoreModule,
8
    IgxDataChartInteractivityModule, IgxDataChartScatterModule, IgxDataChartStackedModule,
9
    IgxItemLegendModule, IgxLegendModule,
10
    IgxNumericXAxisModule, IgxNumericYAxisModule
11
} from 'igniteui-angular-charts';
12

13
import { AutoPositionStrategy, CloseScrollStrategy, HorizontalAlignment, IgxOverlayService, OverlayCancelableEventArgs, OverlayEventArgs, OverlaySettings, VerticalAlignment } from 'igniteui-angular/core';
14
import { IgxIconButtonDirective, IgxToggleDirective } from 'igniteui-angular/directives';
15
import { IgxTabContentComponent, IgxTabHeaderComponent, IgxTabHeaderLabelDirective, IgxTabItemComponent, IgxTabsComponent } from 'igniteui-angular/tabs';
16
import { IgxIconComponent } from 'igniteui-angular/icon';
17

18
import { IgxContextMenuDirective } from './igx-context-menu.directive';
19
import { IgxChartMenuComponent } from './chart-dialog/chart-dialog.component';
20
import { SvgPipe } from '../pipes/svg.pipe';
21
import * as charts from '../../images/charts';
22
import * as conditions from '../../images/conditions';
23
import { CHART_TYPE } from '../directives/chart-integration/chart-types';
24

25
@Component({
26
    selector: 'igx-context-menu',
27
    templateUrl: './context-menu.component.html',
28
    styleUrls: ['./context-menu.component.scss'],
29
    imports: [
30
        CommonModule,
31
        SvgPipe,
32
        IgxToggleDirective,
33
        IgxIconComponent,
34
        IgxTabsComponent,
35
        IgxTabItemComponent,
36
        IgxTabHeaderComponent,
37
        IgxTabContentComponent,
38
        IgxTabHeaderLabelDirective,
39
        IgxBarSeriesModule,
40
        IgxCategoryChartModule,
41
        IgxCategoryXAxisModule,
42
        IgxDataChartCategoryModule,
43
        IgxDataChartCoreModule,
44
        IgxDataChartInteractivityModule,
45
        IgxDataChartScatterModule,
46
        IgxDataChartStackedModule,
47
        IgxItemLegendModule,
48
        IgxLegendModule,
49
        IgxNumericXAxisModule,
50
        IgxNumericYAxisModule,
51
        IgxIconButtonDirective
52
    ],
53
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
54
})
55
export class IgxContextMenuComponent implements AfterViewInit, OnDestroy {
1✔
56
    @ViewChild('analyticsBtn') public button: ElementRef;
57
    @ViewChild('tabsMenu', { read: IgxToggleDirective }) public tabsMenu: IgxToggleDirective;
58
    @ViewChild('chartPreview', { read: ViewContainerRef }) public chartPreview: ViewContainerRef;
59
    @ViewChild('chartPreviewDialog', { read: IgxToggleDirective }) public chartPreviewDialog: IgxToggleDirective;
60
    @ViewChild(IgxTabsComponent) public tabs: IgxTabsComponent;
61

62
    public contextDirective: IgxContextMenuDirective;
63
    public chartTypes = [];
22✔
64
    public textFormatters = [];
22✔
65
    public currentChartType;
66
    public currentFormatter;
67
    public displayCreationTab = true;
22✔
68
    private destroy$ = new Subject<any>();
22✔
69
    private _dialogId;
70
    private _chartDialogOS: OverlaySettings = { closeOnOutsideClick: false };
22✔
71

72
    private _tabsMenuOverlaySettings: OverlaySettings = {
22✔
73
        closeOnOutsideClick: false,
74
        modal: false,
75
        outlet: null,
76
        scrollStrategy: new CloseScrollStrategy(),
77
        positionStrategy: new AutoPositionStrategy({
78
            horizontalDirection: HorizontalAlignment.Center,
79
            horizontalStartPoint: HorizontalAlignment.Center,
80
            verticalStartPoint: VerticalAlignment.Bottom,
81
            verticalDirection: VerticalAlignment.Bottom,
82
            openAnimation: null,
83
            closeAnimation: null,
84
        }),
85
    };
86

87
    private _chartPreviewDialogOverlaySettings: OverlaySettings = {
22✔
88
        closeOnOutsideClick: false,
89
        modal: false,
90
        outlet: null,
91
        scrollStrategy: new CloseScrollStrategy(),
92
        positionStrategy: new AutoPositionStrategy({
93
            horizontalDirection: HorizontalAlignment.Center,
94
            horizontalStartPoint: HorizontalAlignment.Center,
95
            verticalStartPoint: VerticalAlignment.Top,
96
            verticalDirection: VerticalAlignment.Top,
97
            openAnimation: null,
98
            closeAnimation: null,
99
        }),
100
    };
101

102
    public chartImages;
103
    public conditionImages;
104
    private overlayService = inject(IgxOverlayService);
22✔
105

106
    constructor() {
107
        this.chartImages = charts;
22✔
108
        this.conditionImages = conditions;
22✔
109
    }
110

111
    public ngAfterViewInit() {
112
        this.chartTypes = this.contextDirective.charts;
23✔
113
        this.textFormatters = this.contextDirective.formatters;
23✔
114
        this.displayCreationTab = this.contextDirective.displayCreationTab;
23✔
115

116
        if (this.contextDirective.chartsDirective) {
23✔
117
            this.contextDirective.chartsDirective.chartTypesDetermined.pipe(takeUntil(this.destroy$))
23✔
118
                .subscribe((args) => (this.chartTypes = args.chartsForCreation));
1✔
119
        }
120

121
        if (this.contextDirective.textFormatter) {
23✔
122
            this.contextDirective.textFormatter.formattersReady.pipe(takeUntil(this.destroy$))
23✔
123
                .subscribe((names) => (this.textFormatters = names));
1✔
124
        }
125

126
        this.contextDirective.buttonClose.pipe(takeUntil(this.destroy$))
23✔
127
            .subscribe(() => {
128
                if (this.tabsMenu && !this.tabsMenu.collapsed) {
2✔
129
                    this.tabsMenu.close();
1✔
130
                }
131
            });
132

133
        this.contextDirective.gridResizeNotify.pipe(takeUntil(this.destroy$))
23✔
134
            .subscribe(() => {
135
                if (!this.tabsMenu.collapsed) {
1✔
136
                    this.tabsMenu.close();
1✔
137
                }
138
            });
139

140
        this.overlayService.opening.pipe(takeUntil(this.destroy$))
23✔
141
            .subscribe((args: OverlayCancelableEventArgs) => {
142
                if (args.componentRef) {
2✔
143
                    const instance = args.componentRef.instance as IgxChartMenuComponent;
2✔
144
                    instance.width = this.contextDirective.grid.nativeElement.clientWidth;
2✔
145
                    instance.height = this.contextDirective.grid.nativeElement.clientHeight;
2✔
146
                    instance.currentChartType = this.currentChartType;
2✔
147
                    instance.allCharts = this.chartTypes;
2✔
148
                    instance.chartDirective = this.contextDirective.chartsDirective;
2✔
149
                    // TODO: This code handles resizing for a fullscreen dialog when the chart dialog resize event is triggered.  
150
                    // Currently, it determines the visible child element by filtering based on visibility and CSS classes,  
151
                    // which is not a reliable or optimal approach. Instead, this should be improved by properly handling  
152
                    // when elements in the overlay are detached and ensuring chart dialog is only available. 
153
                    instance.chartDialogResizeNotify?.subscribe(resizedContentArgs => {
2✔
NEW
154
                        if ((this.overlayService as any)._overlayElement) {
×
NEW
155
                            const overlayElement = (this.overlayService as any)._overlayElement;
×
NEW
156
                            const visibleChild = Array.from(overlayElement.children).find(
×
157
                                (child: HTMLElement) =>
NEW
158
                                    getComputedStyle(child).visibility !== 'hidden' &&
×
159
                                    child.classList.contains('igx-overlay__wrapper--flex')
160
                            ) as HTMLElement | null;
NEW
161
                            if (visibleChild) {
×
NEW
162
                                const targetElement = visibleChild.children[0] as HTMLElement | null;
×
NEW
163
                                if (targetElement && targetElement.style) {
×
NEW
164
                                    targetElement.style.width = resizedContentArgs[0].contentRect.width + 'px';
×
165
                                }
166
                            }
167
                        }
168
                    });
169
                    instance.closed?.subscribe(() => this.closeDialog());
2✔
170
                }
171
            });
172

173
        this.overlayService.closing.pipe(takeUntil(this.destroy$))
23✔
174
            .subscribe((args: OverlayEventArgs) => {
NEW
175
                if (args.componentRef && args.componentRef.instance instanceof IgxChartMenuComponent) {
×
NEW
176
                    if (this._dialogId) {
×
NEW
177
                        this.tabsMenu.open(this._tabsMenuOverlaySettings);
×
178
                    }
179
                }
180
            });
181
    }
182

183
    public ngOnDestroy(): void {
184
        this.destroy$.next(true);
22✔
185
        this.destroy$.complete();
22✔
186
    }
187

188
    public toggleTabMenu() {
189
        this.currentChartType = this.currentChartType || CHART_TYPE.ColumnGrouped;
3✔
190
        this._tabsMenuOverlaySettings.target = this.button.nativeElement;
3✔
191
        if (this.tabsMenu.collapsed) {
3✔
192
            this.tabsMenu.open(this._tabsMenuOverlaySettings);
2✔
193
        } else {
194
            this.tabsMenu.close();
1✔
195
        }
196
    }
197

198
    public formatCells(condition) {
199
        this.currentFormatter = condition;
1✔
200
        this.contextDirective.textFormatter.formatCells(condition);
1✔
201
    }
202

203
    public clearFormat() {
204
        this.contextDirective.textFormatter.clearFormatting();
1✔
205
        this.currentFormatter = undefined;
1✔
206
    }
207

208
    public previewChart(currentChartType) {
209
        this.currentChartType = currentChartType;
1✔
210
        this.chartPreview.clear();
1✔
211
        this.contextDirective.chartsDirective.chartFactory(currentChartType, this.chartPreview);
1✔
212
        this._chartPreviewDialogOverlaySettings.target = this.tabsMenu.element;
1✔
213
        this.chartPreviewDialog.open(this._chartPreviewDialogOverlaySettings);
1✔
214
    }
215

216
    public hidePreview() {
217
        this.chartPreviewDialog.close();
1✔
218
    }
219

220
    public openDialog(type?: CHART_TYPE) {
221
        this.currentChartType =
5✔
222
            type || this.currentChartType || CHART_TYPE.ColumnGrouped;
7✔
223
        this._dialogId = this._dialogId || this.overlayService.attach(IgxChartMenuComponent, this._chartDialogOS);
5✔
224
        this.tabsMenu.close();
5✔
225
        this.overlayService.show(this._dialogId);
5✔
226
    }
227

228
    public closeDialog() {
229
        const info = this.overlayService.getOverlayById(this._dialogId);
3✔
230
        if (info) {
3✔
231
            this.overlayService.hide(this._dialogId);
2✔
232
            this.overlayService.detach(this._dialogId);
2✔
233
            this._dialogId = undefined;
2✔
234
        }
235
    }
236
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc