Skip to content

Commit

Permalink
fix(positioning): use inject for NgbRTL dependency
Browse files Browse the repository at this point in the history
Fixes #4403
  • Loading branch information
maxokorokov committed Dec 13, 2022
1 parent f427c22 commit 7f2146d
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 91 deletions.
6 changes: 2 additions & 4 deletions src/datepicker/datepicker-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {

import { ngbAutoClose } from '../util/autoclose';
import { ngbFocusTrap } from '../util/focus-trap';
import { PlacementArray, ngbPositioning } from '../util/positioning';
import { ngbPositioning, PlacementArray } from '../util/positioning';
import { Options } from '@popperjs/core';

import { NgbDateAdapter } from './adapters/ngb-date-adapter';
Expand All @@ -43,7 +43,6 @@ import { NgbDatepickerConfig } from './datepicker-config';
import { isString } from '../util/util';
import { Subject } from 'rxjs';
import { addPopperOffset } from '../util/positioning-util';
import { NgbRTL } from '../util/rtl';

/**
* A directive that allows to stick a datepicker popup to an input field.
Expand Down Expand Up @@ -299,15 +298,14 @@ export class NgbInputDatepicker implements OnChanges, OnDestroy, ControlValueAcc
private _ngZone: NgZone,
private _calendar: NgbCalendar,
private _dateAdapter: NgbDateAdapter<any>,
rtl: NgbRTL,
@Inject(DOCUMENT) private _document: any,
private _changeDetector: ChangeDetectorRef,
config: NgbInputDatepickerConfig,
) {
['autoClose', 'container', 'positionTarget', 'placement', 'popperOptions'].forEach(
(input) => (this[input] = config[input]),
);
this._positioning = ngbPositioning(rtl);
this._positioning = ngbPositioning();
}

registerOnChange(fn: (value: any) => any): void {
Expand Down
12 changes: 5 additions & 7 deletions src/dropdown/dropdown.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AfterContentInit,
ChangeDetectorRef,
ContentChild,
ContentChildren,
Expand All @@ -9,22 +10,20 @@ import {
Inject,
Input,
NgZone,
AfterContentInit,
OnChanges,
OnDestroy,
Optional,
Output,
QueryList,
Renderer2,
SimpleChanges,
Optional,
OnChanges,
} from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { fromEvent, Subject, Subscription } from 'rxjs';
import { take } from 'rxjs/operators';

import { Placement, PlacementArray, ngbPositioning } from '../util/positioning';
import { ngbPositioning, Placement, PlacementArray } from '../util/positioning';
import { Options } from '@popperjs/core';
import { NgbRTL } from '../util/rtl';
import { addPopperOffset } from '../util/positioning-util';
import { ngbAutoClose, SOURCE } from '../util/autoclose';
import { Key } from '../util/key';
Expand Down Expand Up @@ -245,7 +244,6 @@ export class NgbDropdown implements AfterContentInit, OnChanges, OnDestroy {

constructor(
private _changeDetector: ChangeDetectorRef,
rtl: NgbRTL,
config: NgbDropdownConfig,
@Inject(DOCUMENT) private _document: any,
private _ngZone: NgZone,
Expand All @@ -258,7 +256,7 @@ export class NgbDropdown implements AfterContentInit, OnChanges, OnDestroy {
this.container = config.container;
this.autoClose = config.autoClose;

this._positioning = ngbPositioning(rtl);
this._positioning = ngbPositioning();
this.display = ngbNavbar ? 'static' : 'dynamic';
}

Expand Down
4 changes: 1 addition & 3 deletions src/popover/popover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import { listenToTriggers } from '../util/triggers';
import { ngbAutoClose } from '../util/autoclose';
import { ngbPositioning, PlacementArray } from '../util/positioning';
import { PopupService } from '../util/popup';
import { NgbRTL } from '../util/rtl';
import { isString } from '../util/util';

import { NgbPopoverConfig } from './popover-config';
Expand Down Expand Up @@ -211,7 +210,6 @@ export class NgbPopover implements OnInit, OnDestroy, OnChanges {

constructor(
private _elementRef: ElementRef<HTMLElement>,
rtl: NgbRTL,
private _renderer: Renderer2,
injector: Injector,
viewContainerRef: ViewContainerRef,
Expand All @@ -231,7 +229,7 @@ export class NgbPopover implements OnInit, OnDestroy, OnChanges {
this.popoverClass = config.popoverClass;
this.openDelay = config.openDelay;
this.closeDelay = config.closeDelay;
this._positioning = ngbPositioning(rtl);
this._positioning = ngbPositioning();
this._popupService = new PopupService<NgbPopoverWindow>(
NgbPopoverWindow,
injector,
Expand Down
28 changes: 13 additions & 15 deletions src/tooltip/tooltip.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import {
ApplicationRef,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ComponentRef,
Directive,
Input,
Output,
ElementRef,
EventEmitter,
ChangeDetectionStrategy,
OnInit,
OnDestroy,
Inject,
Injector,
Input,
NgZone,
OnChanges,
OnDestroy,
OnInit,
Output,
Renderer2,
ComponentRef,
ElementRef,
SimpleChanges,
TemplateRef,
ViewContainerRef,
NgZone,
ViewEncapsulation,
ChangeDetectorRef,
ApplicationRef,
OnChanges,
SimpleChanges,
} from '@angular/core';
import { DOCUMENT } from '@angular/common';

Expand All @@ -28,7 +28,6 @@ import { ngbAutoClose } from '../util/autoclose';
import { ngbPositioning, PlacementArray } from '../util/positioning';
import { PopupService } from '../util/popup';
import { Options } from '@popperjs/core';
import { NgbRTL } from '../util/rtl';
import { isString } from '../util/util';

import { NgbTooltipConfig } from './tooltip-config';
Expand Down Expand Up @@ -171,7 +170,6 @@ export class NgbTooltip implements OnInit, OnDestroy, OnChanges {

constructor(
private _elementRef: ElementRef<HTMLElement>,
rtl: NgbRTL,
private _renderer: Renderer2,
injector: Injector,
viewContainerRef: ViewContainerRef,
Expand Down Expand Up @@ -199,7 +197,7 @@ export class NgbTooltip implements OnInit, OnDestroy, OnChanges {
this._ngZone,
applicationRef,
);
this._positioning = ngbPositioning(rtl);
this._positioning = ngbPositioning();
}

/**
Expand Down
12 changes: 5 additions & 7 deletions src/typeahead/typeahead.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
ApplicationRef,
ChangeDetectorRef,
ComponentRef,
Directive,
Expand All @@ -9,15 +10,14 @@ import {
Injector,
Input,
NgZone,
OnChanges,
OnDestroy,
OnInit,
Output,
Renderer2,
SimpleChanges,
TemplateRef,
ViewContainerRef,
ApplicationRef,
OnChanges,
SimpleChanges,
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { DOCUMENT } from '@angular/common';
Expand All @@ -28,8 +28,7 @@ import { Live } from '../util/accessibility/live';
import { ngbAutoClose } from '../util/autoclose';
import { Key } from '../util/key';
import { PopupService } from '../util/popup';
import { NgbRTL } from '../util/rtl';
import { PlacementArray, ngbPositioning } from '../util/positioning';
import { ngbPositioning, PlacementArray } from '../util/positioning';
import { Options } from '@popperjs/core';
import { isDefined, toString } from '../util/util';

Expand Down Expand Up @@ -200,7 +199,6 @@ export class NgbTypeahead implements ControlValueAccessor, OnInit, OnChanges, On

constructor(
private _elementRef: ElementRef<HTMLInputElement>,
rtl: NgbRTL,
viewContainerRef: ViewContainerRef,
private _renderer: Renderer2,
injector: Injector,
Expand Down Expand Up @@ -233,7 +231,7 @@ export class NgbTypeahead implements ControlValueAccessor, OnInit, OnChanges, On
this._ngZone,
applicationRef,
);
this._positioning = ngbPositioning(rtl);
this._positioning = ngbPositioning();
}

ngOnInit(): void {
Expand Down
120 changes: 66 additions & 54 deletions src/util/positioning.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getBootstrapBaseClassPlacement, getPopperClassPlacement, ngbPositioning, Placement } from './positioning';
import { Placement as PopperPlacement } from '@popperjs/core';
import { NgbRTL } from './rtl';
import { ComponentFixture, fakeAsync, flushMicrotasks, TestBed } from '@angular/core/testing';
import { ComponentFixture, fakeAsync, flushMicrotasks, inject, TestBed } from '@angular/core/testing';
import { createGenericTestComponent } from '../test/common';
import { Component } from '@angular/core';
import { NgbTooltip } from '../tooltip/tooltip';
Expand Down Expand Up @@ -101,61 +101,73 @@ describe('positioning', () => {
}
});

it('should update classes correctly on DOM elements', (done) => {
const testCases = [
['top', 'bs-base-top'],
['bottom', 'bs-base-bottom'],
['start', 'bs-base-start'],
['left', 'bs-base-start'],
['end', 'bs-base-end'],
['right', 'bs-base-end'],
['top-start', 'bs-base-top bs-base-top-start'],
['top-left', 'bs-base-top bs-base-top-start'],
['top-end', 'bs-base-top bs-base-top-end'],
['top-right', 'bs-base-top bs-base-top-end'],
['bottom-start', 'bs-base-bottom bs-base-bottom-start'],
['bottom-left', 'bs-base-bottom bs-base-bottom-start'],
['bottom-end', 'bs-base-bottom bs-base-bottom-end'],
['bottom-right', 'bs-base-bottom bs-base-bottom-end'],
['start-top', 'bs-base-start bs-base-start-top'],
['left-top', 'bs-base-start bs-base-start-top'],
['start-bottom', 'bs-base-start bs-base-start-bottom'],
['left-bottom', 'bs-base-start bs-base-start-bottom'],
['end-top', 'bs-base-end bs-base-end-top'],
['right-top', 'bs-base-end bs-base-end-top'],
['top', 'bs-base-top'],
];

const positioning = ngbPositioning({ isRTL: () => false } as NgbRTL);
const options = {
targetElement: document.createElement('div'),
hostElement: document.createElement('div'),
placement: 'top',
baseClass: 'bs-base',
};
positioning.createPopper(options);

function nextTest() {
if (testCases.length === 0) {
done();
return;
}

const [placement, expectedClassName] = testCases.shift()!;
positioning.setOptions({ ...options, placement });

// checking DOM after popper does 'forceUpdate'
queueMicrotask(() => {
expect(options.targetElement.className).toBe(
expectedClassName,
`Testing '${placement}' mapping to '${expectedClassName}'`,
);
describe('ngbPositioning', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{ provide: NgbRTL, useValue: { isRTL: () => false } },
{ provide: 'ngbPositioning', useFactory: () => ngbPositioning() },
],
});
});

setTimeout(nextTest);
}

nextTest();
it('should update classes correctly on DOM elements', (done) => {
inject(['ngbPositioning'], (positioning) => {
const testCases = [
['top', 'bs-base-top'],
['bottom', 'bs-base-bottom'],
['start', 'bs-base-start'],
['left', 'bs-base-start'],
['end', 'bs-base-end'],
['right', 'bs-base-end'],
['top-start', 'bs-base-top bs-base-top-start'],
['top-left', 'bs-base-top bs-base-top-start'],
['top-end', 'bs-base-top bs-base-top-end'],
['top-right', 'bs-base-top bs-base-top-end'],
['bottom-start', 'bs-base-bottom bs-base-bottom-start'],
['bottom-left', 'bs-base-bottom bs-base-bottom-start'],
['bottom-end', 'bs-base-bottom bs-base-bottom-end'],
['bottom-right', 'bs-base-bottom bs-base-bottom-end'],
['start-top', 'bs-base-start bs-base-start-top'],
['left-top', 'bs-base-start bs-base-start-top'],
['start-bottom', 'bs-base-start bs-base-start-bottom'],
['left-bottom', 'bs-base-start bs-base-start-bottom'],
['end-top', 'bs-base-end bs-base-end-top'],
['right-top', 'bs-base-end bs-base-end-top'],
['top', 'bs-base-top'],
];

const options = {
targetElement: document.createElement('div'),
hostElement: document.createElement('div'),
placement: 'top',
baseClass: 'bs-base',
};
positioning.createPopper(options);

function nextTest() {
if (testCases.length === 0) {
done();
return;
}

const [placement, expectedClassName] = testCases.shift()!;
positioning.setOptions({ ...options, placement });

// checking DOM after popper does 'forceUpdate'
queueMicrotask(() => {
expect(options.targetElement.className).toBe(
expectedClassName,
`Testing '${placement}' mapping to '${expectedClassName}'`,
);
});

setTimeout(nextTest);
}

nextTest();
})();
});
});

describe('rtl', () => {
Expand Down
5 changes: 4 additions & 1 deletion src/util/positioning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Options,
} from '@popperjs/core';
import { NgbRTL } from './rtl';
import { inject } from '@angular/core';

const placementSeparator = /\s+/;
const spacesRegExp = / +/gi;
Expand Down Expand Up @@ -210,7 +211,9 @@ interface PositioningOptions {
function noop(arg) {
return arg;
}
export function ngbPositioning(rtl: NgbRTL) {

export function ngbPositioning() {
const rtl = inject(NgbRTL);
let popperInstance: Instance | null = null;

return {
Expand Down

0 comments on commit 7f2146d

Please sign in to comment.