Skip to content

Commit 117b450

Browse files
wnvkoLipata
authored andcommitted
feat(overlay): add global container position strategy #5667
1 parent 269d9c0 commit 117b450

File tree

13 files changed

+116
-15
lines changed

13 files changed

+116
-15
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ For more information about the theming please read our [documentation](https://w
4747
- Drop strategies. Three new drop strategies have been provided - Append, Prepend and Insert. Also an input `dropStrategy` to the `igxDrop` which specify which strategy should be used when dropping an element inside the drop area. Custom one can be specified as well.
4848
- `IgxCheckbox`
4949
- introduced a new `readonly` property that doesn't allow user interaction to change the state, but keeps the default active style. Intended for integration in complex controls that handle the interaction and control the checkbox instead through binding.
50+
- `IgxOverlay`
51+
- introduced a new `ContainerPositionStrategy`. The new strategy positions the element inside the containing outlet based on the directions passed in trough PositionSettings.
5052

5153
### General
5254
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`

projects/igniteui-angular/src/lib/core/styles/components/overlay/_overlay-component.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
@extend %overlay-wrapper--flex !optional;
2626
}
2727

28+
@include e(wrapper, $m: flex-container) {
29+
@extend %overlay-wrapper !optional;
30+
@extend %overlay-wrapper--flex-container !optional;
31+
}
32+
2833
@include e(content) {
2934
@extend %overlay-content !optional;
3035
}

projects/igniteui-angular/src/lib/core/styles/components/overlay/_overlay-theme.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@
7070
display: flex;
7171
}
7272

73+
%overlay-wrapper--flex-container {
74+
display: flex;
75+
position: absolute;
76+
}
77+
7378
%overlay-content {
7479
position: absolute;
7580
pointer-events: all;

projects/igniteui-angular/src/lib/grids/grid-base.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import { IgxGridCellComponent } from './cell.component';
5050
import { IColumnVisibilityChangedEventArgs } from './column-hiding-item.directive';
5151
import { IgxColumnComponent, IgxColumnGroupComponent } from './column.component';
5252
import { ISummaryExpression } from './summaries/grid-summary';
53-
import { DropPosition, ContainerPositioningStrategy, IgxDecimalPipeComponent, IgxDatePipeComponent } from './grid.common';
53+
import { DropPosition, RowEditPositionStrategy, IgxDecimalPipeComponent, IgxDatePipeComponent } from './grid.common';
5454
import { IgxGridToolbarComponent } from './grid-toolbar.component';
5555
import { IgxRowComponent } from './row.component';
5656
import { IgxGridHeaderComponent } from './grid-header.component';
@@ -2557,7 +2557,7 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
25572557
private _cellSelectionMode = GridSelectionMode.multiple;
25582558
private _rowSelectionMode = GridSelectionMode.none;
25592559

2560-
private rowEditPositioningStrategy = new ContainerPositioningStrategy({
2560+
private rowEditPositioningStrategy = new RowEditPositionStrategy({
25612561
horizontalDirection: HorizontalAlignment.Right,
25622562
verticalDirection: VerticalAlignment.Bottom,
25632563
horizontalStartPoint: HorizontalAlignment.Left,

projects/igniteui-angular/src/lib/grids/grid.common.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -714,17 +714,17 @@ export class IgxDecimalPipeComponent extends DecimalPipe implements PipeTransfor
714714
/**
715715
* @hidden
716716
*/
717-
export interface ContainerPositionSettings extends PositionSettings {
717+
export interface RowEditPositionSettings extends PositionSettings {
718718
container?: HTMLElement;
719719
}
720720

721721
/**
722722
* @hidden
723723
*/
724-
export class ContainerPositioningStrategy extends ConnectedPositioningStrategy {
724+
export class RowEditPositionStrategy extends ConnectedPositioningStrategy {
725725
isTop = false;
726726
isTopInitialPosition = null;
727-
public settings: ContainerPositionSettings;
727+
public settings: RowEditPositionSettings;
728728
position(contentElement: HTMLElement, size: { width: number, height: number }, document?: Document, initialCall?: boolean): void {
729729
const container = this.settings.container; // grid.tbody
730730
const target = <HTMLElement>this.settings.target; // current grid.row

projects/igniteui-angular/src/lib/services/overlay/overlay.spec.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { IgxDatePickerComponent, IgxDatePickerModule } from '../../date-picker/d
4141
import { IPositionStrategy } from './position/IPositionStrategy';
4242
import { IgxCalendarContainerComponent } from '../../date-picker/calendar-container.component';
4343
import { BaseFitPositionStrategy } from './position/base-fit-position-strategy';
44+
import { ContainerPositionStrategy } from './position';
4445

4546
const CLASS_OVERLAY_CONTENT = 'igx-overlay__content';
4647
const CLASS_OVERLAY_CONTENT_MODAL = 'igx-overlay__content--modal';
@@ -2407,6 +2408,46 @@ describe('igxOverlay', () => {
24072408
expect(overlay.hide).toHaveBeenCalledTimes(0);
24082409
}));
24092410

2411+
// 1.5 GlobalContainer.
2412+
it('Should center the shown component in the outlet.', fakeAsync(() => {
2413+
const fixture = TestBed.createComponent(EmptyPageComponent);
2414+
2415+
const outlet = fixture.componentInstance.divElement;
2416+
const outletElement = outlet.nativeElement;
2417+
outletElement.style.width = '800px';
2418+
outletElement.style.height = '600px';
2419+
outletElement.style.position = 'fixed';
2420+
outletElement.style.top = '100px';
2421+
outletElement.style.left = '200px';
2422+
outletElement.style.overflow = 'hidden';
2423+
2424+
fixture.detectChanges();
2425+
const overlaySettings: OverlaySettings = {
2426+
outlet: outlet,
2427+
positionStrategy: new ContainerPositionStrategy()
2428+
};
2429+
2430+
const id = fixture.componentInstance.overlay.attach(SimpleDynamicComponent);
2431+
fixture.componentInstance.overlay.show(id, overlaySettings);
2432+
tick();
2433+
2434+
const overlayDiv = outletElement.children[0];
2435+
const overlayDivRect = overlayDiv.getBoundingClientRect();
2436+
expect(overlayDivRect.width).toEqual(800);
2437+
expect(overlayDivRect.height).toEqual(600);
2438+
2439+
const overlayWrapper = overlayDiv.children[0] as HTMLElement;
2440+
const componentEl = overlayWrapper.children[0].children[0];
2441+
const componentRect = componentEl.getBoundingClientRect();
2442+
2443+
// left = outletLeft + (outletWidth - componentWidth) / 2
2444+
// left = 200 + (800 - 100 ) / 2
2445+
expect(componentRect.left).toEqual(550);
2446+
// top = outletTop + (outletHeight - componentHeight) / 2
2447+
// top = 100 + (600 - 100 ) / 2
2448+
expect(componentRect.top).toEqual(350);
2449+
}));
2450+
24102451
// 3. Interaction
24112452
// 3.1 Modal
24122453
it('Should apply a greyed-out mask layers when is modal.', fakeAsync(() => {

projects/igniteui-angular/src/lib/services/overlay/position/README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,26 @@ Position strategies determine where to display the component in the provided Igx
77
|:---------------------------|:-------------------------|
88
| HorizontalAlignment.Center | VerticalAlignment.Middle |
99

10+
2) **Container** - Positions the element inside the containing outlet based on the directions passed in trough PositionSettings. These are Top/Middle/Bottom for verticalDirection and Left/Center/Right for horizontalDirection. Defaults to:
1011

11-
2) **Connected** - Positions the element based on the directions and start point passed in trough PositionSettings. It is possible to either pass a start point or an HTMLElement as a positioning base. Defaults to:
12+
| horizontalDirection | verticalDirection |
13+
|:---------------------------|:-------------------------|
14+
| HorizontalAlignment.Center | VerticalAlignment.Middle |
15+
16+
17+
3) **Connected** - Positions the element based on the directions and start point passed in trough PositionSettings. It is possible to either pass a start point or an HTMLElement as a positioning base. Defaults to:
1218

1319
| target | horizontalDirection | verticalDirection | horizontalStartPoint | verticalStartPoint |
1420
|:----------------|:--------------------------|:-------------------------|:-------------------------|:-------------------------|
1521
| new Point(0, 0) | HorizontalAlignment.Right | VerticalAlignment.Bottom | HorizontalAlignment.Left | VerticalAlignment.Bottom |
1622

17-
3) **Auto** - Positions the element as in **Connected** positioning strategy and re-positions the element in the view port (calculating a different start point) in case the element is partially getting out of view. Defaults to:
23+
4) **Auto** - Positions the element as in **Connected** positioning strategy and re-positions the element in the view port (calculating a different start point) in case the element is partially getting out of view. Defaults to:
1824

1925
| target | horizontalDirection | verticalDirection | horizontalStartPoint | verticalStartPoint |
2026
|:----------------|:--------------------------|:-------------------------|:-------------------------|:-------------------------|
2127
| new Point(0, 0) | HorizontalAlignment.Right | VerticalAlignment.Bottom | HorizontalAlignment.Left | VerticalAlignment.Bottom |
2228

23-
4) **Elastic** - Positions the element as in **Connected** positioning strategy and resize the element to fit in the view port in case the element is partially getting out of view. Defaults to:
29+
5) **Elastic** - Positions the element as in **Connected** positioning strategy and resize the element to fit in the view port in case the element is partially getting out of view. Defaults to:
2430

2531
| target | horizontalDirection | verticalDirection | horizontalStartPoint | verticalStartPoint | minSize |
2632
|:----------------|:--------------------------|:-------------------------|:-------------------------|:-------------------------|-------------------------|
@@ -58,6 +64,7 @@ import {AutoPositionStrategy, GlobalPositionStrategy, ConnectedPositioningStrate
5864
| Position Strategy | Name | Description |
5965
|:------------------|:-------------------------------------------------------|:----------------------------------------------------------------------------------|
6066
| Global | `position(contentElement)` | Positions the element, based on the horizontal and vertical directions. |
67+
| Container | `position(contentElement)` | Positions the element inside the containing outlet based on the directions passed in trough PositionSettings. |
6168
| Connected | `position(contentElement, size{})` | Positions the element, based on the position strategy used and the size passed in.|
6269
| Auto | `position(contentElement, size{}, document?)` | Positions the element, based on the position strategy used and the size passed in.|
6370
| Elastic | `position(contentElement, size{}, document?, minSize?)`| Positions the element, based on the position strategy used and the size passed in.|
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { PositionSettings, Size } from '../utilities';
2+
import { GlobalPositionStrategy } from './global-position-strategy';
3+
4+
/**
5+
* Positions the element inside the containing outlet based on the directions passed in trough PositionSettings.
6+
* These are Top/Middle/Bottom for verticalDirection and Left/Center/Right for horizontalDirection
7+
*/
8+
export class ContainerPositionStrategy extends GlobalPositionStrategy {
9+
constructor(settings?: PositionSettings) {
10+
super(settings);
11+
}
12+
13+
/** @inheritdoc */
14+
position(contentElement: HTMLElement, size?: Size, document?: Document, initialCall?: boolean): void {
15+
contentElement.classList.add('igx-overlay__content--relative');
16+
contentElement.parentElement.classList.add('igx-overlay__wrapper--flex-container');
17+
this.setPosition(contentElement, this.settings);
18+
}
19+
}
20+

projects/igniteui-angular/src/lib/services/overlay/position/global-position-strategy.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { IPositionStrategy } from './IPositionStrategy';
2-
import { PositionSettings, HorizontalAlignment, VerticalAlignment, Size, Util } from './../utilities';
2+
import { PositionSettings, HorizontalAlignment, VerticalAlignment, Size, Util, OverlaySettings } from './../utilities';
33
import { fadeIn, fadeOut } from '../../../animations/main';
44

55
/**
66
* Positions the element based on the directions passed in trough PositionSettings.
77
* These are Top/Middle/Bottom for verticalDirection and Left/Center/Right for horizontalDirection
88
*/
99
export class GlobalPositionStrategy implements IPositionStrategy {
10-
private _defaultSettings: PositionSettings = {
10+
protected _defaultSettings: PositionSettings = {
1111
horizontalDirection: HorizontalAlignment.Center,
1212
verticalDirection: VerticalAlignment.Middle,
1313
horizontalStartPoint: HorizontalAlignment.Center,
@@ -24,9 +24,14 @@ export class GlobalPositionStrategy implements IPositionStrategy {
2424
this.settings = Object.assign({}, this._defaultSettings, settings);
2525
}
2626

27+
/** @inheritdoc */
2728
position(contentElement: HTMLElement, size?: Size, document?: Document, initialCall?: boolean): void {
2829
contentElement.classList.add('igx-overlay__content--relative');
2930
contentElement.parentElement.classList.add('igx-overlay__wrapper--flex');
31+
this.setPosition(contentElement, this.settings);
32+
}
33+
34+
protected setPosition(contentElement: HTMLElement, settings: PositionSettings) {
3035
switch (this.settings.horizontalDirection) {
3136
case HorizontalAlignment.Left:
3237
contentElement.parentElement.style.justifyContent = 'flex-start';
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
12
// Export position strategies
23
export * from './IPositionStrategy';
34
export * from './global-position-strategy';
5+
export * from './container-position-strategy';
46
export * from './connected-positioning-strategy';
57
export * from './auto-position-strategy';
68
export * from './elastic-position-strategy';

0 commit comments

Comments
 (0)