Skip to content

Commit d072852

Browse files
authored
feat(overlay): use ViewContainerRef to create components #11671 (#11685)
1 parent e5e95ba commit d072852

File tree

11 files changed

+235
-99
lines changed

11 files changed

+235
-99
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ All notable changes for each version of this project will be documented in this
3232
- Added `shape` property that controls the shape of the badge and can be either `square` or `rounded`. The default shape of the badge is rounded.
3333
- `IgxAvatar`
3434
- **Breaking Change** The `roundShape` property has been deprecated and will be removed in a future version. Users can control the shape of the avatar by the newly added `shape` attribute that can be `square`, `rounded` or `circle`. The default shape of the avatar is `square`.
35+
- `IgxOverlayService`
36+
- `attach` method overload accepting `ComponentFactoryResolver` (trough `NgModuleRef`-like object) is now deprecated in line with API deprecated in Angular 13. New overload is added accepting `ViewComponentRef` that should be used instead.
3537

3638

3739
## 15.0.1

projects/igniteui-angular/src/lib/calendar/calendar-multi-view.component.spec.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,9 @@ describe('Multi-View Calendar - ', () => {
13171317
overlay = document.querySelector(HelperTestFunctions.OVERLAY_CSSCLASS);
13181318
HelperTestFunctions.verifyMonthsViewNumber(overlay, 2);
13191319
HelperTestFunctions.verifyCalendarSubHeaders(overlay, [new Date('2019-09-16'), new Date('2019-10-16')]);
1320+
1321+
// clean up test
1322+
tick(350);
13201323
}));
13211324

13221325
it('Verify setting hideOutsideDays and monthsViewNumber from datepicker', fakeAsync(() => {
@@ -1349,8 +1352,10 @@ describe('Multi-View Calendar - ', () => {
13491352
expect(HelperTestFunctions.getHiddenDays(overlay, 0).length).toBe(0);
13501353
expect(HelperTestFunctions.getHiddenDays(overlay, 1).length).toBe(0);
13511354
expect(HelperTestFunctions.getHiddenDays(overlay, 2).length).toBe(0);
1352-
}));
13531355

1356+
// clean up test
1357+
tick(350);
1358+
}));
13541359
});
13551360
});
13561361

projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,14 @@ describe('IgxDatePicker', () => {
114114
fixture.detectChanges();
115115

116116
datePicker.close();
117-
tick();
117+
tick(350);
118118
fixture.detectChanges();
119119
expect(datePicker.collapsed).toBeFalsy();
120120
expect(datePicker.closing.emit).toHaveBeenCalled();
121121
expect(datePicker.closed.emit).not.toHaveBeenCalled();
122122

123123
closingSub.unsubscribe();
124+
(datePicker as any)._overlayService.detachAll();
124125
}));
125126
});
126127

@@ -176,6 +177,9 @@ describe('IgxDatePicker', () => {
176177
expect(datePicker.collapsed).toBeFalsy();
177178
expect(datePicker.opening.emit).toHaveBeenCalledTimes(1);
178179
expect(datePicker.opened.emit).toHaveBeenCalledTimes(1);
180+
181+
// wait datepicker to get destroyed and test to cleanup
182+
tick(350);
179183
}));
180184

181185
it('should close the calendar with ESC', fakeAsync(() => {
@@ -455,7 +459,7 @@ describe('IgxDatePicker', () => {
455459
let mockDateEditor: any;
456460
let mockCalendar: Partial<IgxCalendarComponent>;
457461
let mockInputDirective: any;
458-
const mockModuleRef = {} as any;
462+
const viewsContainerRef = {} as any;
459463
const mockOverlayId = '1';
460464
const today = new Date();
461465
const elementRef = {
@@ -625,10 +629,11 @@ describe('IgxDatePicker', () => {
625629
},
626630
focus: () => { }
627631
};
628-
datePicker = new IgxDatePickerComponent(elementRef, 'en-US', overlay, mockModuleRef, mockInjector, renderer2, null, mockCdr);
632+
datePicker = new IgxDatePickerComponent(elementRef, 'en-US', overlay, mockInjector, renderer2, null, mockCdr);
629633
(datePicker as any).inputGroup = mockInputGroup;
630634
(datePicker as any).inputDirective = mockInputDirective;
631635
(datePicker as any).dateTimeEditor = mockDateEditor;
636+
(datePicker as any).viewContainerRef = viewsContainerRef;
632637
// TODO: TEMP workaround for afterViewInit call in unit tests:
633638
datePicker.clearComponents = new QueryList<any>();
634639
datePicker.toggleComponents = new QueryList<any>();
@@ -886,19 +891,19 @@ describe('IgxDatePicker', () => {
886891
const isDropdownSpy = spyOnProperty(datePicker, 'isDropdown', 'get');
887892
isDropdownSpy.and.returnValue(false);
888893
datePicker.open();
889-
expect(overlay.attach).toHaveBeenCalledWith(IgxCalendarContainerComponent, baseDialogSettings, mockModuleRef);
894+
expect(overlay.attach).toHaveBeenCalledWith(IgxCalendarContainerComponent, viewsContainerRef, baseDialogSettings);
890895
expect(overlay.show).toHaveBeenCalledWith(mockOverlayId);
891896
isDropdownSpy.and.returnValue(true);
892897
datePicker.open();
893-
expect(overlay.attach).toHaveBeenCalledWith(IgxCalendarContainerComponent, baseDropdownSettings, mockModuleRef);
898+
expect(overlay.attach).toHaveBeenCalledWith(IgxCalendarContainerComponent, viewsContainerRef, baseDropdownSettings);
894899
expect(overlay.show).toHaveBeenCalledWith(mockOverlayId);
895900
const mockOutlet = {} as any;
896901
datePicker.outlet = mockOutlet;
897902
datePicker.open();
898903
expect(overlay.attach).toHaveBeenCalledWith(
899904
IgxCalendarContainerComponent,
905+
viewsContainerRef,
900906
Object.assign({}, baseDropdownSettings, { outlet: mockOutlet }),
901-
mockModuleRef
902907
);
903908
expect(overlay.show).toHaveBeenCalledWith(mockOverlayId);
904909
let mockSettings: OverlaySettings = {
@@ -910,8 +915,8 @@ describe('IgxDatePicker', () => {
910915
datePicker.open(mockSettings);
911916
expect(overlay.attach).toHaveBeenCalledWith(
912917
IgxCalendarContainerComponent,
918+
viewsContainerRef,
913919
Object.assign({}, baseDropdownSettings, mockSettings),
914-
mockModuleRef
915920
);
916921
expect(overlay.show).toHaveBeenCalledWith(mockOverlayId);
917922
isDropdownSpy.and.returnValue(false);
@@ -923,8 +928,8 @@ describe('IgxDatePicker', () => {
923928
datePicker.open(mockSettings);
924929
expect(overlay.attach).toHaveBeenCalledWith(
925930
IgxCalendarContainerComponent,
931+
viewsContainerRef,
926932
Object.assign({}, baseDialogSettings, mockSettings),
927-
mockModuleRef
928933
);
929934
expect(overlay.show).toHaveBeenCalledWith(mockOverlayId);
930935
isDropdownSpy.and.returnValue(true);
@@ -937,8 +942,8 @@ describe('IgxDatePicker', () => {
937942
datePicker.open(mockSettings);
938943
expect(overlay.attach).toHaveBeenCalledWith(
939944
IgxCalendarContainerComponent,
945+
viewsContainerRef,
940946
Object.assign({}, baseDropdownSettings, { modal: true }),
941-
mockModuleRef
942947
);
943948
});
944949

projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,77 @@
11
import {
2-
Component, ContentChild, EventEmitter, HostBinding, Input,
3-
OnDestroy, Output, ViewChild, ElementRef, Inject, HostListener,
4-
NgModuleRef, OnInit, AfterViewInit, Injector, AfterViewChecked, ContentChildren,
5-
QueryList, LOCALE_ID, Renderer2, Optional, PipeTransform, ChangeDetectorRef
2+
AfterViewChecked,
3+
AfterViewInit,
4+
ChangeDetectorRef,
5+
Component,
6+
ContentChild,
7+
ContentChildren,
8+
ElementRef,
9+
EventEmitter,
10+
HostBinding,
11+
HostListener,
12+
Inject,
13+
Injector,
14+
Input,
15+
LOCALE_ID,
16+
OnDestroy,
17+
OnInit,
18+
Optional,
19+
Output,
20+
PipeTransform,
21+
QueryList,
22+
Renderer2,
23+
ViewChild,
24+
ViewContainerRef
625
} from '@angular/core';
726
import {
8-
ControlValueAccessor, NG_VALUE_ACCESSOR, NgControl, AbstractControl,
9-
NG_VALIDATORS, ValidationErrors, Validator
27+
AbstractControl,
28+
ControlValueAccessor,
29+
NgControl,
30+
NG_VALIDATORS,
31+
NG_VALUE_ACCESSOR,
32+
ValidationErrors,
33+
Validator
1034
} from '@angular/forms';
11-
import {
12-
IgxCalendarComponent, IgxCalendarHeaderTemplateDirective, IgxCalendarSubheaderTemplateDirective,
13-
isDateInRanges, IFormattingViews, IFormattingOptions
14-
} from '../calendar/public_api';
15-
import {
16-
IgxInputDirective, IgxInputGroupComponent,
17-
IgxLabelDirective, IGX_INPUT_GROUP_TYPE, IgxInputGroupType, IgxInputState
18-
} from '../input-group/public_api';
19-
import { fromEvent, Subscription, noop, MonoTypeOperatorFunction } from 'rxjs';
35+
import { fromEvent, MonoTypeOperatorFunction, noop, Subscription } from 'rxjs';
2036
import { filter, takeUntil } from 'rxjs/operators';
21-
import { IgxOverlayOutletDirective } from '../directives/toggle/toggle.directive';
37+
import { fadeIn, fadeOut } from '../animations/fade';
2238
import {
23-
OverlaySettings, IgxOverlayService, AbsoluteScrollStrategy,
24-
AutoPositionStrategy,
25-
OverlayCancelableEventArgs,
26-
OverlayEventArgs
27-
} from '../services/public_api';
28-
import { CurrentResourceStrings } from '../core/i18n/resources';
29-
import { IDatePickerResourceStrings } from '../core/i18n/date-picker-resources';
39+
IFormattingOptions,
40+
IFormattingViews,
41+
IgxCalendarComponent,
42+
IgxCalendarHeaderTemplateDirective,
43+
IgxCalendarSubheaderTemplateDirective,
44+
isDateInRanges
45+
} from '../calendar/public_api';
3046
import { DateRangeDescriptor, DateRangeType } from '../core/dates/dateRange';
31-
import { IBaseCancelableBrowserEventArgs, PlatformUtil, isDate } from '../core/utils';
47+
import { DisplayDensityToken, IDisplayDensityOptions } from '../core/density';
48+
import { IDatePickerResourceStrings } from '../core/i18n/date-picker-resources';
49+
import { CurrentResourceStrings } from '../core/i18n/resources';
50+
import { IBaseCancelableBrowserEventArgs, isDate, PlatformUtil } from '../core/utils';
3251
import { IgxCalendarContainerComponent } from '../date-common/calendar-container/calendar-container.component';
33-
import { fadeIn, fadeOut } from '../animations/fade';
3452
import { PickerBaseDirective } from '../date-common/picker-base.directive';
35-
import { DisplayDensityToken, IDisplayDensityOptions } from '../core/density';
36-
import { DatePart, DatePartDeltas, IgxDateTimeEditorDirective } from '../directives/date-time-editor/public_api';
53+
import { IgxPickerActionsDirective, IgxPickerClearComponent } from '../date-common/public_api';
54+
import { PickerHeaderOrientation } from '../date-common/types';
3755
import { DateTimeUtil } from '../date-common/util/date-time.util';
38-
import { PickerHeaderOrientation as PickerHeaderOrientation } from '../date-common/types';
56+
import { DatePart, DatePartDeltas, IgxDateTimeEditorDirective } from '../directives/date-time-editor/public_api';
57+
import { IgxOverlayOutletDirective } from '../directives/toggle/toggle.directive';
58+
import {
59+
IgxInputDirective,
60+
IgxInputGroupComponent,
61+
IgxInputGroupType,
62+
IgxInputState,
63+
IgxLabelDirective,
64+
IGX_INPUT_GROUP_TYPE
65+
} from '../input-group/public_api';
66+
import {
67+
AbsoluteScrollStrategy,
68+
AutoPositionStrategy,
69+
IgxOverlayService,
70+
OverlayCancelableEventArgs,
71+
OverlayEventArgs,
72+
OverlaySettings
73+
} from '../services/public_api';
3974
import { IDatePickerValidationFailedEventArgs } from './date-picker.common';
40-
import { IgxPickerClearComponent, IgxPickerActionsDirective } from '../date-common/public_api';
4175

4276
let NEXT_ID = 0;
4377

@@ -378,6 +412,9 @@ export class IgxDatePickerComponent extends PickerBaseDirective implements Contr
378412
@ViewChild(IgxInputGroupComponent)
379413
private inputGroup: IgxInputGroupComponent;
380414

415+
@ViewChild(IgxInputGroupComponent, { read: ViewContainerRef })
416+
private viewContainerRef: ViewContainerRef;
417+
381418
@ViewChild(IgxLabelDirective)
382419
private labelDirective: IgxLabelDirective;
383420

@@ -467,7 +504,6 @@ export class IgxDatePickerComponent extends PickerBaseDirective implements Contr
467504
constructor(public element: ElementRef<HTMLElement>,
468505
@Inject(LOCALE_ID) protected _localeId: string,
469506
@Inject(IgxOverlayService) private _overlayService: IgxOverlayService,
470-
private _moduleRef: NgModuleRef<any>,
471507
private _injector: Injector,
472508
private _renderer: Renderer2,
473509
private platform: PlatformUtil,
@@ -541,9 +577,8 @@ export class IgxDatePickerComponent extends PickerBaseDirective implements Contr
541577
if (this.outlet) {
542578
overlaySettings.outlet = this.outlet;
543579
}
544-
545580
this._overlayId = this._overlayService
546-
.attach(IgxCalendarContainerComponent, overlaySettings, this._moduleRef);
581+
.attach(IgxCalendarContainerComponent, this.viewContainerRef, overlaySettings);
547582
this._overlayService.show(this._overlayId);
548583
}
549584

projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.spec.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ describe('IgxDateRangePicker', () => {
5454
let mockPlatformUtil: any;
5555
let overlay: IgxOverlayService;
5656
let mockInjector;
57-
let ngModuleRef: any;
5857
let mockCalendar: IgxCalendarComponent;
5958
let mockDaysView: any;
6059
let mockAnimationService: AnimationService;
@@ -77,13 +76,6 @@ describe('IgxDateRangePicker', () => {
7776
})
7877
})
7978
};
80-
ngModuleRef = ({
81-
injector: (...args: any[]) => { },
82-
componentFactoryResolver: mockFactoryResolver,
83-
instance: () => { },
84-
destroy: () => { },
85-
onDestroy: (fn: any) => { }
86-
});
8779
mockElement = {
8880
style: { visibility: '', cursor: '', transitionDuration: '' },
8981
classList: { add: () => { }, remove: () => { } },
@@ -123,7 +115,14 @@ describe('IgxDateRangePicker', () => {
123115
getPosition: () => 0,
124116
parentPlayer: {},
125117
totalTime: 0,
126-
beforeDestroy: () => { }
118+
beforeDestroy: () => { },
119+
_renderer: {
120+
engine: {
121+
players: [
122+
{}
123+
]
124+
}
125+
}
127126
})
128127
})
129128
};
@@ -255,7 +254,7 @@ describe('IgxDateRangePicker', () => {
255254
});
256255

257256
it('should disable calendar dates when min and/or max values as dates are provided', () => {
258-
const dateRange = new IgxDateRangePickerComponent(elementRef, 'en-US', platform, mockInjector, ngModuleRef, null, overlay);
257+
const dateRange = new IgxDateRangePickerComponent(elementRef, 'en-US', platform, mockInjector, null, overlay);
259258
dateRange.ngOnInit();
260259

261260
spyOnProperty((dateRange as any), 'calendar').and.returnValue(mockCalendar);
@@ -775,6 +774,9 @@ describe('IgxDateRangePicker', () => {
775774
fixture.detectChanges();
776775

777776
expect((dateRange as any).calendar.selectedDates.length).toBeGreaterThan(0);
777+
778+
// clean up test
779+
tick(350);
778780
}));
779781

780782
it('should set initial validity state when the form group is disabled', () => {
@@ -1036,12 +1038,12 @@ describe('IgxDateRangePicker', () => {
10361038
const fix = TestBed.createComponent(DateRangeReactiveFormComponent);
10371039
fix.detectChanges();
10381040
const dateRangePicker = fix.componentInstance.dateRangeWithTwoInputs;
1039-
1041+
10401042
fix.componentInstance.markAsTouched();
10411043
fix.detectChanges();
10421044
expect(dateRangePicker.projectedInputs.first.inputDirective.valid).toBe(IgxInputState.INVALID);
10431045
expect(dateRangePicker.projectedInputs.last.inputDirective.valid).toBe(IgxInputState.INVALID);
1044-
1046+
10451047
fix.componentInstance.disableForm();
10461048
fix.detectChanges();
10471049
expect(dateRangePicker.projectedInputs.first.inputDirective.valid).toBe(IgxInputState.INITIAL);
@@ -1349,6 +1351,9 @@ describe('IgxDateRangePicker', () => {
13491351
dateRange.select(startDate, endDate);
13501352
fixture.detectChanges();
13511353
expect(singleInputElement.nativeElement.getAttribute('placeholder')).toEqual('');
1354+
1355+
// clean up test
1356+
tick(350);
13521357
}));
13531358

13541359
it('should render custom label', () => {

0 commit comments

Comments
 (0)