Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contextmenu is broken in Angular 13 #242

Open
elementalTIMING opened this issue Nov 4, 2021 · 16 comments
Open

Contextmenu is broken in Angular 13 #242

elementalTIMING opened this issue Nov 4, 2021 · 16 comments

Comments

@elementalTIMING
Copy link

The contextmenu doesn't open anymore on right click. The error message:

´this.overlay.position(...).connectedTo is not a function´

comes up. Does anybody how to fix this?

Thx and best regards,
Lars

@elementalTIMING
Copy link
Author

Ok, I found a fix which seems to work. But to be honest, I have no idea if this covers all issues - for me it is working

In file contextMenu.service.tssearch for first occurrence of (line 82):

const positionStrategy = this.overlay.position().connectedTo( ... )

Replace with:

const positionStrategy = this.overlay
	.position()
	.flexibleConnectedTo(new ElementRef(anchorElement || this.fakeElement))
	.withPositions([
		{
			originX: 'start',
			originY: 'top',
			overlayX: 'start',
			overlayY: 'top',
		},
		{
			originX: 'start',
			originY: 'top',
			overlayX: 'start',
			overlayY: 'bottom',
		},
		{
			originX: 'end',
			originY: 'top',
			overlayX: 'start',
			overlayY: 'top',
		},
		{
			originX: 'start',
			originY: 'top',
			overlayX: 'end',
			overlayY: 'top',
		},
		{
			originX: 'end',
			originY: 'center',
			overlayX: 'start',
			overlayY: 'center',
		},
		{
			originX: 'end',
			originY: 'center',
			overlayX: 'start',
			overlayY: 'center',
		},
		{
			originX: 'start',
			originY: 'center',
			overlayX: 'end',
			overlayY: 'center',
		},
	])
	.withFlexibleDimensions(false);

In file contextMenu.service.tssearch for first occurrence of (line 109):

const positionStrategy = this.overlay.position().connectedTo( ... )

Replace with:

  const positionStrategy = this.overlay
    .position()
    .flexibleConnectedTo(new ElementRef(anchorElement || this.fakeElement))
    .withPositions([
      {
        originX: 'start',
        originY: 'top',
        overlayX: 'end',
        overlayY: 'top',
      },
      {
        originX: 'end',
        originY: 'bottom',
        overlayX: 'start',
        overlayY: 'bottom',
      },
      {
        originX: 'start',
        originY: 'bottom',
        overlayX: 'end',
        overlayY: 'bottom',
      },
    ])
    .withFlexibleDimensions(false)

Doing so the context menu will work with Angular 13, too. Nevertheless, I would be grateful if the developer would provide an official fix, because I'm not sure if this fix really covers all aspects of CDK API changes.

Another issue in Angular 13:

I'm using two different context menus on one page but in different components. In the past I did in each component

// template
<context-menu>
	...
</context-menu>

// component
@ViewChild(ContextMenuComponent, { static: true }) public basicContextMenu: ContextMenuComponent;

...and this was working well. With Angular 13 you have to give each context menu an unique name, like

<context-menu #basicDrawingContextMenu>
	...
</context-menu>

and in the component:

@ViewChild('basicDrawingContextMenu') public basicContextMenu: ContextMenuComponent;

If not doing this - the second context menu will not contain any elements.

Hope that the code fragments here will help some people to update to Angular 13

@mrjohnr
Copy link

mrjohnr commented Nov 11, 2021

same here.not working for angular 13,waiting for a fix

@Cosangeles33
Copy link

I'm really looking forward to the fix ( @sroucheray

@MichalK6677
Copy link

I temporarily implemented fix from @elementalPRESS this way:

contextMenu.service.ts

import { Overlay, ScrollStrategyOptions } from '@angular/cdk/overlay';
import { ElementRef, Injectable } from '@angular/core';
import { ContextMenuService, IContextMenuContext } from 'ngx-contextmenu';

@Injectable({
    providedIn: 'root'
})`
export class ContextMenuFixService extends ContextMenuService {
    constructor(
        private overlayFix: Overlay,
        private scrollStrategyFix: ScrollStrategyOptions,
    ) {
        super(overlayFix, scrollStrategyFix);
    }

    public openContextMenu(context: IContextMenuContext) {
        const { anchorElement, event, parentContextMenu } = context;

        if (!parentContextMenu) {
            const mouseEvent = event as MouseEvent;
            this['fakeElement'].getBoundingClientRect = (): DOMRect => ({
                bottom: mouseEvent.clientY,
                height: 0,
                left: mouseEvent.clientX,
                right: mouseEvent.clientX,
                top: mouseEvent.clientY,
                width: 0,
            } as DOMRect);
            this.closeAllContextMenus({ eventType: 'cancel', event });
            const positionStrategy = this.overlayFix
                .position()
                .flexibleConnectedTo(new ElementRef(anchorElement || this['fakeElement']))
                .withPositions([
                    {
                        originX: 'start',
                        originY: 'top',
                        overlayX: 'start',
                        overlayY: 'top',
                    },
                    {
                        originX: 'start',
                        originY: 'top',
                        overlayX: 'start',
                        overlayY: 'bottom',
                    },
                    {
                        originX: 'end',
                        originY: 'top',
                        overlayX: 'start',
                        overlayY: 'top',
                    },
                    {
                        originX: 'start',
                        originY: 'top',
                        overlayX: 'end',
                        overlayY: 'top',
                    },
                    {
                        originX: 'end',
                        originY: 'center',
                        overlayX: 'start',
                        overlayY: 'center',
                    },
                    {
                        originX: 'end',
                        originY: 'center',
                        overlayX: 'start',
                        overlayY: 'center',
                    },
                    {
                        originX: 'start',
                        originY: 'center',
                        overlayX: 'end',
                        overlayY: 'center',
                    },
                ])
                .withFlexibleDimensions(false);
            this['overlays'] = [this.overlayFix.create({
                positionStrategy,
                panelClass: 'ngx-contextmenu',
                scrollStrategy: this.scrollStrategyFix.close(),
            })];
            this.attachContextMenu(this['overlays'][0], context);
        } else {
            const positionStrategy = this.overlayFix
                .position()
                .flexibleConnectedTo(new ElementRef(anchorElement || this['fakeElement']))
                .withPositions([
                    {
                        originX: 'start',
                        originY: 'top',
                        overlayX: 'end',
                        overlayY: 'top',
                    },
                    {
                        originX: 'end',
                        originY: 'bottom',
                        overlayX: 'start',
                        overlayY: 'bottom',
                    },
                    {
                        originX: 'start',
                        originY: 'bottom',
                        overlayX: 'end',
                        overlayY: 'bottom',
                    },
                ])
                .withFlexibleDimensions(false)
            const newOverlay = this.overlayFix.create({
                positionStrategy,
                panelClass: 'ngx-contextmenu',
                scrollStrategy: this.scrollStrategyFix.close(),
            });
            this.destroySubMenus(parentContextMenu);
            this['overlays'] = this['overlays'].concat(newOverlay);
            this.attachContextMenu(newOverlay, context);
        }
    }
}

app.module.ts

providers: [
        ...,
        {
            provide: ContextMenuService,
            useExisting: ContextMenuFixService
        }
]

@sroucheray
Copy link
Contributor

sroucheray commented Nov 22, 2021

I'm really looking forward to the fix ( @sroucheray

Sorry but I am not the maintainer

@RGerhardt-Pressmind
Copy link

When is this change finally coming to the live repo? You can't upgrade to Angular 13 and unfortunately you have to wait.

@56789a1987
Copy link

@MichalK6677 the fix has issues. The menu position is incorrect for submenus or using with anchorElement.
Made some fix by referring to the original source code.

contextMenu.service.ts

import { Overlay, ScrollStrategyOptions } from '@angular/cdk/overlay';
import { ElementRef, Injectable } from '@angular/core';
import { ContextMenuService, IContextMenuContext } from 'ngx-contextmenu';

@Injectable({
	providedIn: 'root'
})
export class ContextMenuFixService extends ContextMenuService {
	constructor(private overlayFix: Overlay, private scrollStrategyFix: ScrollStrategyOptions) {
		super(overlayFix, scrollStrategyFix);
	}

	public openContextMenu(context: IContextMenuContext) {
		const { anchorElement, event, parentContextMenu } = context;

		if (!parentContextMenu) {
			const mouseEvent = event as MouseEvent;
			this['fakeElement'].getBoundingClientRect = (): DOMRect => ({
				bottom: mouseEvent.clientY,
				height: 0,
				left: mouseEvent.clientX,
				right: mouseEvent.clientX,
				top: mouseEvent.clientY,
				width: 0,
			} as DOMRect);
			this.closeAllContextMenus({ eventType: 'cancel', event });
			const positionStrategy = this.overlayFix
				.position()
				.flexibleConnectedTo(new ElementRef(anchorElement || this['fakeElement']))
				.withPositions([
					{
						originX: 'start', originY: 'bottom',
						overlayX: 'start', overlayY: 'top',
					},
					{
						originX: 'start', originY: 'top',
						overlayX: 'start', overlayY: 'bottom',
					},
					{
						originX: 'end', originY: 'top',
						overlayX: 'start', overlayY: 'top',
					},
					{
						originX: 'start', originY: 'top',
						overlayX: 'end', overlayY: 'top',
					},
					{
						originX: 'end', originY: 'center',
						overlayX: 'start', overlayY: 'center',
					},
					{
						originX: 'start', originY: 'center',
						overlayX: 'end', overlayY: 'center',
					},
				])
				.withFlexibleDimensions(false);
			this['overlays'] = [this.overlayFix.create({
				positionStrategy,
				panelClass: 'ngx-contextmenu',
				scrollStrategy: this.scrollStrategyFix.close(),
			})];
			this.attachContextMenu(this['overlays'][0], context);
		} else {
			const positionStrategy = this.overlayFix
				.position()
				.flexibleConnectedTo(new ElementRef(event ? event.target : anchorElement))
				.withPositions([
					{
						originX: 'end', originY: 'top',
						overlayX: 'start', overlayY: 'top',
					},
					{
						originX: 'start', originY: 'top',
						overlayX: 'end', overlayY: 'top',
					},
					{
						originX: 'end', originY: 'bottom',
						overlayX: 'start', overlayY: 'bottom',
					},
					{
						originX: 'start', originY: 'bottom',
						overlayX: 'end', overlayY: 'bottom',
					},
				])
				.withFlexibleDimensions(false);
			const newOverlay = this.overlayFix.create({
				positionStrategy,
				panelClass: 'ngx-contextmenu',
				scrollStrategy: this.scrollStrategyFix.close(),
			});
			this.destroySubMenus(parentContextMenu);
			this['overlays'] = this['overlays'].concat(newOverlay);
			this.attachContextMenu(newOverlay, context);
		}
	}
}

@eran10
Copy link

eran10 commented Dec 26, 2021

any update here ? we also can't upgrade to Angular 13...
any chance to push a fix @isaacplmann ?

@MaximeKoitsalu
Copy link

I think this project has been abandoned by the maintainer, maybe some brave soul would dare fork this project and maintain it by themself?

hoeni pushed a commit to hoeni/ngx-contextmenu that referenced this issue Jan 13, 2022
@mrjohnr
Copy link

mrjohnr commented Jan 18, 2022

@hoeni: how to update to your commit? npm shows no new version

@hoeni
Copy link

hoeni commented Jan 18, 2022

@hoeni: how to update to your commit? npm shows no new version

You should not. I was just experimenting...

@mrjohnr
Copy link

mrjohnr commented Jan 20, 2022

Has anyone successfully using this component on Angular 13?

@RGerhardt-Pressmind
Copy link

Has anyone successfully using this component on Angular 13?

Yes, ist work in Angular 13 with the bugfix from @56789a1987

@mrjohnr
Copy link

mrjohnr commented Jan 20, 2022

so how to make it works,any steps?
thanks

Has anyone successfully using this component on Angular 13?

Yes, ist work in Angular 13 with the bugfix from @56789a1987

@sroucheray
Copy link
Contributor

sroucheray commented Jan 20, 2022

For those in need of Angular 13 support, I forked the project here https://github.com/PerfectMemory/ngx-contextmenu/ and published updated versions here https://www.npmjs.com/package/@perfectmemory/ngx-contextmenu

I did it because obviously, @isaacplmann, the maintainer is not willing to keep up with Angular versions. It is his strictest right. I take this opportunity to thank him warmly for his work that I have used for several years.

To get a drop in replacement of the [email protected] (Angular 12)

npm install @perfectmemory/[email protected]

this is mainly the same code base as this one, apart from the package name and some cosmetic and config file changes.

To get Angular 13 support

npm install @perfectmemory/ngx-contextmenu@^7.0.0

This is an updated version and the API has not changed.

Both versions are still alpha because they are barely tested. Not much work have been done on top of @isaacplmann 's.

Both versions are now tested with increasing code coverage.

@mrjohnr
Copy link

mrjohnr commented Jan 21, 2022

great

remove "ngx-contextmenu": "6.0.0",  
add @perfectmemory/ngx-contextmenu": "7.0.0-alpha.1"
use new import:  import { ContextMenuModule, ContextMenuService } from '@perfectmemory/ngx-contextmenu';
add in syled.css   @import '@angular/cdk/overlay-prebuilt.css';

is woking,thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants