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

IgniteUI / igniteui-angular / 28358286454

29 Jun 2026 08:17AM UTC coverage: 90.127% (-0.05%) from 90.174%
28358286454

Pull #17246

github

web-flow
Merge 21687d939 into 07bdcd752
Pull Request #17246: fix(pivot-grid): fix date format based on the localization

14921 of 17392 branches covered (85.79%)

Branch coverage included in aggregate %.

29 of 32 new or added lines in 4 files covered. (90.63%)

735 existing lines in 76 files now uncovered.

29992 of 32441 relevant lines covered (92.45%)

34632.46 hits per line

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

85.29
/projects/igniteui-angular-extras/src/lib/context-menu/context-menu.component.ts
1
import { AfterViewInit, Component, ElementRef, ViewChild, ViewContainerRef, OnDestroy, CUSTOM_ELEMENTS_SCHEMA, inject, ChangeDetectionStrategy } 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
    changeDetection: ChangeDetectionStrategy.Eager,
54
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
55
})
56
export class IgxContextMenuComponent implements AfterViewInit, OnDestroy {
1✔
57
    @ViewChild('analyticsBtn') public button: ElementRef;
58
    @ViewChild('tabsMenu', { read: IgxToggleDirective }) public tabsMenu: IgxToggleDirective;
59
    @ViewChild('chartPreview', { read: ViewContainerRef }) public chartPreview: ViewContainerRef;
60
    @ViewChild('chartPreviewDialog', { read: IgxToggleDirective }) public chartPreviewDialog: IgxToggleDirective;
61
    @ViewChild(IgxTabsComponent) public tabs: IgxTabsComponent;
62

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

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

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

103
    public chartImages;
104
    public conditionImages;
105
    private overlayService = inject(IgxOverlayService);
29✔
106

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

229
    public closeDialog() {
230
        const info = this.overlayService.getOverlayById(this._dialogId);
3✔
231
        if (info) {
3✔
232
            this.overlayService.hide(this._dialogId);
2✔
233
            this.overlayService.detach(this._dialogId);
2✔
234
            this._dialogId = undefined;
2✔
235
        }
236
    }
237
}
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