英文:
Getting templateRef of host component in directive
问题
Component1: 我有一个组件,其中包含ng-template和其下的内容
<ng-template #content><ng-content></ng-content></ng-template>
Directive: 在我的指令中,我尝试获取templateRef,但它总是为空。 (在ViewInit和ContentAfterInit中都尝试过) (我必须将这个模板引用传递给一个服务,以便打开模态框)
@ViewChild('content') public templateref: TemplateRef<any>;
Usage:
<app-component1 directive1> <app-anothercomponent>.....<app-component2> .... </app-component1>
是否有可能在指令中获取ng-template的内容?
Slackblitz链接:https://stackblitz.com/edit/angular-directive-view-children-y59xnh?file=app%2Finput-overview-example.html
英文:
Component1: I have a component that has ng-template and content under it
<ng-template #content><ng-content></ng-content></ng-template>
Directive: In my directive, I am trying to get templateRef, but it's always empty. (Tried in ViewInit and ContentAfterInit both) (I have to pass this template ref to a service in order to open the modal)
@ViewChild('content') public templateref: TemplateRef<any>;
Usage:
<app-component1 directive1> <app-anothercomponent>.....<app-component2> .... </app-component1>
Is it even possible to get ng-template content in the directive?
Slackblitz: https://stackblitz.com/edit/angular-directive-view-children-y59xnh?file=app%2Finput-overview-example.html
答案1
得分: 1
我认为您正在询问如何从指令的宿主组件中获取 TemplateRef。
如果您预先知道组件的类型,那么您可以直接从指令中引用它:
export class Directive1Directive implements AfterViewInit {
constructor(@Host() @Self() private host: Component1Component) {}
ngAfterViewInit(): void {
console.log(this.host.templateRef);
}
}
如果您不知道预期的宿主组件类型,情况就会变得更加复杂。通用地将宿主组件注入到指令的最佳方法是让宿主指令实现一个类,并将该组件提供为该类。
您可以首先创建一个具有您想要引用的宿主组件的所有属性的类。在这种情况下,我们只声明了一个公开 TemplateRef 的属性。之所以使用类而不是接口的唯一原因是它减少了使用 InjectionToken 的需要。
export abstract class BaseComponent {
public templateRef?: TemplateRef<any>;
}
宿主组件中唯一需要注意的是,我们需要在其提供者数组中添加一个提供者,该提供者基本上在 BaseComponent 的别名下“重新提供”了自身。函数 forwardRef 用于创建对稍后声明的内容的延迟引用。
@Component({
/*...*/
providers: [{ provide: BaseComponent, useExisting: forwardRef(() => Component1Component) }]
})
export class Component1Component implements BaseComponent {
@ViewChild('content') public templateRef?: TemplateRef<any>;
}
指令基本上没有改变。
export class Directive1Directive implements AfterViewInit {
constructor(private host: BaseComponent) {}
ngAfterViewInit(): void {
console.log(this.host.templateRef);
}
}
本回答的很多内容都来自 How You Can Access All Host Component Details Inside the Directive in Angular。
英文:
What I think you're asking is how do I get a TemplateRef from a Directive's host Component?
If you know the component's type in advance, then you can reference it directly from the directive:
export class Directive1Directive implements AfterViewInit {
constructor(@Host() @Self() private host: Component1Component) {}
ngAvterViewInit(): void {
console.log(this.host.templateRef);
}
}
It becomes more tricky if you don't know the expected host component's type. The best way to generically inject a host component into a directive is to have that host directive implement a class and provide that component as that class.
You can start by creating a class that has all properties from the host component that you want to reference. In this case we're just declaring property that exposes the TemplateRef. The only reason why a class is used over an interface is that it reduces the need for using an InjectionToken.
export abstract class BaseComponent {
public templateRef?: TemplateRef<any>;
}
The only wrinkle in the host component is that we need to a provider is added to its providers array that basically "reprovides" itself under the alias of BaseComponent. The function forwardRef is used to create a deferred reference to something declared later.
@Component({
/*...*/
providers: [{ provide: BaseClass, useExisting: forwardRef(() => Component1Component ) }]
})
export class Component1Component implements BaseComponent {
@ViewChild('content') public templateRef?: TemplateRef<any>;
}
The directive is basically unchanged.
export class Directive1Directive implements AfterViewInit {
constructor(private host: BaseComponent) {}
ngAvterViewInit(): void {
console.log(this.host.templateRef);
}
}
A lot of this answer came from How You Can Access All Host Component Details Inside the Directive in Angular.
答案2
得分: 0
如果你尝试在 `ngOninit` 中获取它,你必须将其声明为静态的:
```typescript
@ViewChild('content', { static: true }) public templateref: TemplateRef<any>;
否则它只能在视图初始化后才可用 (ngAfterViewInit
)。除此之外,这是可能的,并且经常这样做,所以如果你在这方面遇到问题,试着在 stackblitz 上创建一个 MCVE 来展示你的问题。
<details>
<summary>英文:</summary>
If you try getting it in `ngOninit`, you have to declare it as static :
```typescript
@ViewChild('content', { static: true }) public templateref: TemplateRef<any>;
Otherwise it' only avilable after view init (ngAfterViewInit
). Other than that, it is possible and done very often, so if you have an issue doing it, try making a MCVE on stackblitz showing your issue.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论