Angular - child 组件可以引用 parent 的模板变量吗?
Angular - Can a child component reference a parent's template variable?
我正在使用 primefaces primeng 组件开发 angular 4 应用程序,p-contextmenu
。我试图告诉 child 元素使用 parent 组件的模板变量。
app.html:
<div>
<router-outlet></router-outlet>
<div #contextMenuHolder></div>
</div>
mycomponent.html:
<p-contextMenu [appendTo]="contextMenuHolder" [model]="items"></p-contextMenu>
显然它失败了,因为 contextMenuHolder
在 child 中不存在,但在它的 parent 中:
Angular: Identifier 'contextMenuHolder' is not defined. The component declaration, template variable declarations, and element references do not contain such a member
你能从 child 组件引用 parent 的模板变量吗?
编辑:
Plunkr with it broken。这个 plunkr 显示它不工作,但没有错误消息。
appendTo
的文档说
Target element to attach the overlay, valid values are "body" or a local ng-template variable of another element.
也许服务可以解决问题:
@Injectable()
export class ContextMenuHolder {
contextMenu: any; // TODO set a type (HTMLElement?)
getContextMenu() {
return this.contextMenu;
}
setContextMenu(contextMenu: any) {
this.contextMenu = contextMenu;
}
}
在您的 app.ts
中,您注入服务并设置值。
在您的 component.ts
中,您注入服务并获取值。
我没有测试它,但它应该 工作。如果 contextMenu
可以更改,您将不得不使用事件侦听器或可观察的。
感谢 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;
}
}
此处,child 组件已构建上下文菜单,其中包含菜单中所需的项目。此菜单需要驻留在 parent 中(有时这是出于样式或定位原因所必需的)。 child 有一个 parentContext
object 将在生命周期的 onInit
阶段设置。
parent (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)
}
}
parent 在 onInit
阶段在服务中设置 object。最初我认为这必须在 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;
}
}
我正在使用 primefaces primeng 组件开发 angular 4 应用程序,p-contextmenu
。我试图告诉 child 元素使用 parent 组件的模板变量。
app.html:
<div>
<router-outlet></router-outlet>
<div #contextMenuHolder></div>
</div>
mycomponent.html:
<p-contextMenu [appendTo]="contextMenuHolder" [model]="items"></p-contextMenu>
显然它失败了,因为 contextMenuHolder
在 child 中不存在,但在它的 parent 中:
Angular: Identifier 'contextMenuHolder' is not defined. The component declaration, template variable declarations, and element references do not contain such a member
你能从 child 组件引用 parent 的模板变量吗?
编辑:
Plunkr with it broken。这个 plunkr 显示它不工作,但没有错误消息。
appendTo
的文档说
Target element to attach the overlay, valid values are "body" or a local ng-template variable of another element.
也许服务可以解决问题:
@Injectable()
export class ContextMenuHolder {
contextMenu: any; // TODO set a type (HTMLElement?)
getContextMenu() {
return this.contextMenu;
}
setContextMenu(contextMenu: any) {
this.contextMenu = contextMenu;
}
}
在您的 app.ts
中,您注入服务并设置值。
在您的 component.ts
中,您注入服务并获取值。
我没有测试它,但它应该 工作。如果 contextMenu
可以更改,您将不得不使用事件侦听器或可观察的。
感谢 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;
}
}
此处,child 组件已构建上下文菜单,其中包含菜单中所需的项目。此菜单需要驻留在 parent 中(有时这是出于样式或定位原因所必需的)。 child 有一个 parentContext
object 将在生命周期的 onInit
阶段设置。
parent (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)
}
}
parent 在 onInit
阶段在服务中设置 object。最初我认为这必须在 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;
}
}