将模板内容从父项注入子项

时间:2018-10-01 22:21:00

标签: angular

我有一个第三方库组件,我正在尝试通过在特定点添加一些附加标记来自定义。我正在使用结构指令来执行此操作,当前我正在使用渲染器以编程方式添加和样式化节点,如下所示:

  const headerDiv = this.newDiv();
   el = this.nativeElement.querySelector('div.ui-dropdown-items-wrapper');
   this.renderer.appendChild(el, this.renderer.createText('sometext'));


  private newDiv(): Element {
   return this.renderer.createElement('div');
 }

标记如下:

<div #containerDiv>
  <child-component *myStructuralDirective>
  </child-component>
</div>

是否有一种方法可以直接在父组件的标记中定义<ng-template>并使用渲染器在特定点注入它?像这样:

<div #containerDiv>
  <child-component *myStructuralDirective>
  </child-component>
</div>
<ng-template #footer>
   <p>Some other markup</p>
</ng-template>

,然后在我选择的某个时候将#footer的内容注入到子组件中。注意-我无法访问该孩子,因为它是一个已编译的第三方库。

要点是,我试图查看是否有一种更好的方法将标记定义为模板变量,可以在结构指令中使用该模板变量,可以访问该模板并将其注入到子组件。

编辑- 我正在查看ViewContainerRef.insert,很遗憾,这只能根据其他ViewRef的位置插入模板。由于无法更改第三方组件的标记,因此可以定义ng-container来标记插入点,并且只需要使用CSS选择器即可。不知道是否有一种基于元素位置插入模板的方法。我知道这是2个离散的概念(Angular View抽象与直接DOM插入),所以我并不乐观可以做到这一点!

1 个答案:

答案 0 :(得分:2)

是的,您可以使用以下几种方法将ng-template注入到您希望放置的位置:

1。)使用 ng-container

 <div #containerDiv>
  <child-component *myStructuralDirective></child-component>

  // This will show your template
  <ng-container [ngTemplateOutlet]="footer"></ng-container>  

</div>

<ng-template #footer>
   <p>Some other markup</p>
</ng-template>

2。)或使用结构指令和ViewContainerRef&CreateEmbeddedView

注入它
a.)Supply the footer template on your childComponent. myStructuralDirective
is now both a directive and an [] input that asks for a value.

<child-component [myStructuralDirective]="footer"></child-component>

b.) Use default ViewContainerRef declared on the constructor which pertains 
to your current view/screen which the template the template is attached example for this - it is attached on ChildComponentView

@Directive({
    selector: 'myStructuralDirective'
})
export class MyStructuralDirective implements AfterViewInit {

 @Input() myStructuralDirective: TemplateRef<any>;

 constructor(private container: ViewContainerRef) {}

 ngAfterViewInit() {
     this.container.createEmbeddedView(this.myStructuralDirective);
  }
     

}

3。)或在您的ChildComponent上提供@Input(),以传递页脚模板值

 a.)  <child-component *myStructuralDirective
                       [footerTemplate]="footer"></child-component>

 b.) On the ChildComponent Class, declare its @Input() property

 @Component({
     selector: 'child-component'
  })
  export class ChildComponent {

    @Input() footerTemplate: TemplateRef<any>;

  }

 c.) On your ChildComponent Template, supply an ng-container to wherever you want it to be placed.

 <h1>Header</h1>
 <h1>Content</h1>

 <ng-container [ngTemplateOutlet]="footerTemplate"></ng-container>

4。)或者您可以在 ChildComponent

上提供一个容器
  

a。)ChildComponent示例模板

<p>Header</p> 
<p>Content</p>

<div #container></div>
     

b。)使用@Input()在您的ChildComponent类上声明ViewContainerRef和TemplateRef,它需要组件中的页脚模板值

@Component({...})
export class ChildComponent implements AfterViewInit {

  //From your template <div #container></div> 
  @ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef;

  @Input() footerTemplate: TemplateRef<any>;


  ngAfterViewInit() {
     this.container.createEmbeddedView(this.footerTemplate);
}
     

}

您的ng模板现在将出现在您想要的位置。