Closed Jamlearner closed 6 years ago
If you want to wrap the service in a module, put it in the providers
array.
@NgModule({
providers: [
CustomContextmenuService
],
})
export class MyModule {
}
Or you could use it directly like this in your AppModule
:
@NgModule({
imports: [
ContextMenuModule.forRoot(),
],
providers: [
// This replaces all instances of ContextMenuService with your CustomContextmenuService
{ provides: ContextMenuService, useClass: CustomContextmenuService },
],
})
export class AppModule {}
Thanks for your comment!
1) REPLY to: If you want to wrap the service in a module, put it in the providers array.
Relates to a recent closed issue on CustomMenuComponent, I tried to add CustomContextmenuService
to the component but it seems visibleMenuItems:Array
is empty when doing right-clicking.
this.contextMenu-visibleMenuItems:Array
appears to be empty.@Directive({
selector: 'customcontextmenu',
// normal stuff
})
export class CustomMenuComponent {
constructor(
@Host() private contextMenu: ExtendableContextMenuComponent,
private contextMenuService: CustomContextmenuService , <----- i added the custom service
/* whatever other things you want in here */) {
}
// normal life cycle stuff works, reference this.contextMenu to modify the context menu
// i also added contextmenu event to listen, and to call onContextMenu()
onContextMenu($event: MouseEvent, item: any): void {
this.contextMenuService.show.next({
contextMenu: this.contextMenu, <------- <<EMPTY>> visibleMenuItems:Array(0)
event: $event,
item: item
});
$event.preventDefault();
$event.stopPropagation();
}
}
How can I make this.contextMenu to use CustomContextmenuService instead of ContextmenuService? I am guessing this the problem occuring here? I move on to test using the original ContextmenuService instead of CustomContextmenuService and it will work. Is it possible to use CustomContextmenuService in CustomMenuComponent ?
2) REPLY to: Or you could use it directly like this in your AppModule:
I also tried with provides: ContextMenuService, useClass: CustomContextmenuService
but compile error of No provider for CustomContextmenuService!
providers: [
{ provide: ContextMenuService, useClass: CustomContextMenuService }
]
Hi @isaacplmann, I have used useExisting
instead of useClass
to resolve the above issue. Thanks for the tips!
providers: [
CustomContextMenuService,
{ provide: ContextMenuService, useExisting: CustomContextMenuService }
]
It also appears that I am unable to do a proper manual contextmenu listen in AppComponent
with the extended wrapper service contextMenuService: CustomContextMenuService
. The item data went missing...
ngAfterContentInit() {
this.renderer.listen(this.target, 'contextmenu', (event) => this.onContextMenu(event, this.items));
}
onContextMenu($event: MouseEvent, items: any): void {
console.log('items', items); <---- this shows the items correctly
this.contextMenuService.show.next({
contextMenu: this.basicMenu,
event: $event,
item: items <----
});
$event.preventDefault();
$event.stopPropagation();
}
<customcontextmenu #basicMenu>
<ng-template contextMenuItem let-item>
I am {{ item?.name }}
</ng-template>
</customcontextmenu>
When I right click on the target, menu item shows "I am "
instead of "I am Jam"
. It seems like my item get lost somewhere else.
It could be that your CustomContextMenuService
is overriding a method that is supposed to pass on that item data. Since you're changing internals now, it's hard for me to debug without looking at your code.
I'm curious why do you need to extend the service and component? If there's some functionality that you're adding which other people could benefit from, we could talk about submitting a PR.
As a new Angular self-learner, I came across an topic that interests me into doing some dependency injection, directives/components/services wrappers on third-party angular libraries. Looking at your past issues here, I picked up some ideas on extending your directives/components/services as a practical training. Example, allowing users to do a contextmenu event binding via an API, keyboard bindings etc in your library instead of writing the same chunks of codes in their application. I do not know if this is a good idea but it's a basically a fun topic to play with.
Though my CustomContextMenuService
is still empty for now. I am making sure that the original features are working with CustomContextMenuService
before I start writing and testing my custom services/controls.
And so I have an empty CustomContextMenuService
export class CustomContextMenuService extends ContextMenuService {
//empty
}
In AppComponent
I am just attempting to attach the event binding
onContextMenu(event: MouseEvent): void {
this.customContextMenuService .show.next({
contextMenu: this.testContextMenu,
event,
item: this.item
});
event.preventDefault();
event.stopPropagation();
}
<customcontextmenu #testContextMenu>
<ng-template contextMenuItem let-item>
I am {{ item?.name }}
</ng-template>
</customcontextmenu>
I apologize if i bother you.
UPDATE:
I found my silly mistake on why i get "I am "
instead of "I am Jam"
.
I am attaching the contextmenu to a single Element, but I had a mistake of having an array of objects this.items
items = [
{ ..... },
{ ..... }
];
it should be just
items = { ..... };
You're not bothering me at all. I'm glad you chose my library to learn from. If you come up with something cool, consider writing a PR to share it with others.
Let me know if I can explain anything else.
Thanks for spending some time talking through my issues.
I might need some help on calling custom function testFunction
written in CustomMenuComponent
when contextmenu is in different component. This is really a helpful feature if I can do something like an API and use it like this.customMenuComponent.testFunction()
.
ExtendableContextMenuComponent
// copy @Component info from contextMenu.component.ts
@Component({
encapsulation: ViewEncapsulation.None,
selector: 'customcontextmenu',
styles: [`
... copied styles from contextMenu.component.ts ...
`],
template: ` `,
})
export class ExtendableContextMenuComponent extends ContextMenuComponent {
// intentionally empty
}
CustomMenuComponent
@Directive({
selector: 'customcontextmenu',
// normal stuff
})
export class CustomMenuComponent {
constructor(
@Host() private contextMenu: ExtendableContextMenuComponent
...
/* whatever other things you want in here */) {
}
...
...
testFunction() { ... }
}
contextmenu is in different component, so i passed customContextMenu
with @input
to ChildComponent
<app-child [customContextMenu]="customContextMenu"></app-child>
<customcontextmenu #customContextMenu>
... ...
</customcontextmenu>
In ChildComponent
, I am attempting to call testFunction()
with an error TypeError: this.customContextMenu.testFunction() is not a function
.
@Component({
selector: 'app-child ',
})
export class ChildComponent implements OnInit {
@Input() customContextMenu: CustomContextMenu;
ngOnInit() {
this.customContextMenu.testFunction() <----- error
}
}
What I understand for now is there will be error if I use @input() customContextMenu: CustomContextMenu
when contextmenu is in different component,
but when contextmenu is in the same component, I can use @ViewChild
with no issues calling testFunction()
. I am little confuse on how these works for now...
That code looks right to me. If this is just a learning project, why don't you put the repo up on GitHub so I can see the whole thing.
On Mar 7, 2018 1:41 AM, "Jamlearner" notifications@github.com wrote:
Thanks for spending some time talking through my issues.
I might need some help on calling custom function testFunction written in CustomMenuComponent when contextmenu is in different component.
ExtendableContextMenuComponent
// copy @Component info from contextMenu.component.ts @Component({ encapsulation: ViewEncapsulation.None, selector: 'customcontextmenu', styles: [
... copied styles from contextMenu.component.ts ...
], template:, }) export class ExtendableContextMenuComponent extends ContextMenuComponent { // intentionally empty }
CustomMenuComponent
@Directive({ selector: 'customcontextmenu', // normal stuff }) export class CustomMenuComponent { constructor( @Host() private contextMenu: ExtendableContextMenuComponent ... / whatever other things you want in here /) { }
... ...
testFunction() { ... } }
contextmenu is in different component, so i passed customContextMenu with @input to ChildComponent
<app-child [customContextMenu]="customContextMenu"> <customcontextmenu #customContextMenu> ... ...
In ChildComponent, I am attempting to call testFunction() with an error TypeError: this.customContextMenu.testFunction() is not a function.
@Component({ selector: 'app-child ', }) export class ChildComponent implements OnInit { @Input() customContextMenu: CustomContextMenu;
ngOnInit() { this.customContextMenu.testFunction() <----- error }
}
What I understand for now is there will be error if I use @input() customContextMenu: CustomContextMenu when contextmenu is in different component,
but when contextmenu is in the same component, I can use @ViewChild with no issues calling testFunction(). I am little confuse on how these works for now...
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/isaacplmann/ngx-contextmenu/issues/94#issuecomment-371039335, or mute the thread https://github.com/notifications/unsubscribe-auth/AA0lQMuydOtQotY9gWXqPP31BsBgvl9Hks5tb4EIgaJpZM4SZpje .
This will work if you set your second.component.html
to this:
<h1>second.component:</h1>
<h3 style="margin-top:30px;" [contextMenu]="contextMenuDirective" [contextMenuSubject]="items">Manually attaching event if contextmenu in different component</h3>
Or, to make your solution work, do this:
app.component.html
<customcontextmenu #manualAttachingContextMenu="contextMenuDirective">
<ng-template contextMenuItem let-item>
Manually attaching contextmenu event " {{ item.name }} "
</ng-template>
</customcontextmenu>
contextMenu.component.ts
// ...
@Directive({
// tslint:disable-next-line:directive-selector
selector: 'customcontextmenu',
exportAs: 'contextMenuDirective',
})
// tslint:disable-next-line:directive-class-suffix
export class ContextMenuDirective {
// ...
}
I wrote this article about all the different ways you can use template reference variables.
Great stuffs! I like your articles and I will read all of them. Thanks for writing up useful articles.
First solution gives an error of:
Template parse errors: Can't bind to 'contextMenuDirective' since it isn't a known property of 'app-second'.
Second solution works great!
Hi @isaacplmann ,
If I want to extend ContextMenuService,
In AnotherModule, I imported
MyModule
so I can use CustomContextmenuService in AnotherModule? But I met error ofUnexpected value 'ɵa in MyModule ..Please add a @Pipe/@Directive/@Component annotation....
when doingnpm start
Did I missed out something?