[英]How to create an Angular directive that combines multiple templates?
我正在嘗試創建一個自定義指令,允許我從 json / ts object 讀取模板並將其插入我的指令模板中。
例如,在配置文件/數據庫/ts 文件中,我有:
{
//...
text: '<p>Many of our tools ...AD Groups:</p><AD_GROUPS id="AD_GROUPS"></AD_GROUPS><p>To request access, ...',
AD_GROUPS: [
'my-team-users'
],
//...
} // truncated and wrapped for readability
我想從配置文件中獲取文本 (html),將<AD_GROUPS>
標記替換為程序員傳入的模板,並將其呈現到頁面。 該指令是這樣使用的:
<div *appAdGroupText="cfg">
<mat-list>
<mat-list-item *ngFor="let group of cfg.AD_GROUPS">{{group}}</mat-list-item>
</mat-list>
</div>
我創建了指令:
@Directive({selector: '[appAdGroupText]'})
export class AdGroupTextDirective implements OnChanges {
_config: ConfigurationItemModel | undefined;
constructor(
private templateRef: TemplateRef<unknown>,
private vcr: ViewContainerRef,
private renderer: Renderer2
// private resolver: ComponentFactoryResolver
) {
}
@Input() set appAdGroupText(cfg: ConfigurationItemModel) {
this._config = cfg;
this.render();
}
render() {
const cfg = this._config; // config is set in a set method. This has the correct value
const groupListDivElement: HTMLDivElement = this.renderer.createElement('my-group-text'); // creates a 'parent' element
groupListDivElement.innerHTML = cfg.text; // set the inner html to the config text
const adListDivRef = this.templateRef.createEmbeddedView(null); // create an unattached version of the template
// loop through, and replace the "AD_GROUPS" custom tag with the generated template
groupListDivElement.childNodes.forEach(n => {
if (n.nodeName === 'AD_GROUPS') {
n.replaceWith(adListDivRef.rootNodes[0]); // this is incorrect. I only get the root node, rather than the entire node with its children
}
// arguably, the above could be replaced with an Array.from(...) find / replace
console.log(groupListDivElement); // SEE HTML OUTPUT
// How do I render groupListDivElement in the VCR / renderer???
// this works will put the mat-list ONLYin:
// let view = this.templateRef.createEmbeddedView(null);
// this.vcr.insert(view);
}
}
從console.log
生成 HTML :
<my-group-text _ngcontent-hwh-c107="">
<p>Many of our tools are restricted to specific groups in Active Directory. In order to access the required tools, you will need access to the following AD Groups:</p>
<div _ngcontent-hwh-c107="">
<mat-list _ngcontent-hwh-c107="" class="mat-list mat-list-base">
<!--container-->
</mat-list>
</div>
<p>
To request access, <a href="https://access" target="_blank" rel="noopener noreferrer">click here</a> and fill out the form with the following information:
<ad_form_table></ad_form_table>
</p>
<p>You will need to create a ticket for each of the above groups listed.</p>
</ad-group-text>
adListDivRef
附加到正確的父級? 我想我可以這樣訪問父節點: this.renderer.parentNode(this.vcr.element.nativeElement)
?mat-list
似乎沒有從我嵌入的*ngFor
中找到列表項。 我怎么得到它? 我在想也許我的指令首先被調用而下一個沒有被調用?代碼最少的 Stackblitz: https://stackblitz.com/edit/angular-ivy-zv16cn
這里有兩個步驟來實現你的目標:
將生成ag-group-text
元素放入頁面
this.vcr.element.nativeElement.parentNode.appendChild(groupListDivElement);
將適當的context
傳遞到動態生成的模板中
const adListDivRef: EmbeddedViewRef<any> = this.vcr.createEmbeddedView(this.templateRef, { cfg });
注意:使用
ViewContainerRef.createEmbeddedTemplate(templateRef)
確保您無需擔心渲染模板中的變化檢測,因為變化檢測器成為 Angular 變化檢測樹的一部分。 如果是templateRef.create
你必須自己處理變化檢測
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.