感谢 Ludovic Guillaume,我找到了解决方案:
https://plnkr.co/edit/kwnkSKDPFs1Bp2xOHqIu
child.ts:
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {ContextMenuHolderService} from './context-menu-holder.service'
@Component({
selector: 'child-comp',
template: `
<div>
<h2>Hello child</h2>
<span #mySpan>this bit has a context menu</span> <br>
<span #parentSpan>this bit is the target for the parent span.</span>
<p-contextMenu [target]="mySpan" [appendTo]="parentContext" [model]="items"></p-contextMenu>
<p-contextMenu [target]="parentSpan" [appendTo]="parentContext" [model]="itemsForParent"></p-contextMenu>
</div>
`,
})
export class ChildComponent {
private items: MenuItem[];
parentContext: any;
constructor(private cmhs : ContextMenuHolderService) {
}
ngOnInit() {
this.items = [{ label: 'mySpans context menu' }];
this.itemsForParent = [{ label: 'parent context menu items' }];
console.log('child init', this.cmhs.getContextMenuParent())
this.parentContext = this.cmhs.getContextMenuParent().nativeElement;
}
}
在这里,子组件构建了上下文菜单,其中包含它想要的菜单项。此菜单需要驻留在父级中(有时出于样式或定位原因,这是必需的)。孩子有一个 parentContext 对象,该对象将在其生命周期的 onInit 阶段设置。
父级(app.ts):
//our root app component
import {Component, NgModule, VERSION, ViewChild} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {ChildComponent} from './child'
import {ContextMenuModule,MenuItem} from 'primeng/primeng'
import {ContextMenuHolderService} from './context-menu-holder.service'
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<div #parentContextTarget>This is in the parent component and should have a context menu</div>
<div #parentContextWrapper></div>
<child-comp></child-comp>
</div>
`,
})
export class App {
name:string;
@ViewChild('parentContextWrapper') parentContextWrapper;
constructor(private cmhs : ContextMenuHolderService) {
this.name = `Angular! v${VERSION.full}`
// console.log('parent constructor')
}
ngOnInit(){
console.log('parent init - parent context wrapper', this.parentContextWrapper)
this.cmhs.setContextMenuParent(this.parentContextWrapper)
}
}
父级在onInit 阶段将对象设置在服务中。最初我认为这必须是在afterViewInit 期间,但这最终在生命周期中为时已晚。
服务:
import {Injectable} from '@angular/core';
@Injectable()
export class ContextMenuHolderService {
contextMenuParent: any; // TODO set a type (HTMLElement?)
getContextMenuParent() {
console.log('returning cmp', this.contextMenuParent)
return this.contextMenuParent;
}
setContextMenuParent(contextMenuParent: any) {
console.log('settin context menu parent', contextMenuParent)
this.contextMenuParent = contextMenuParent;
}
}