javascript - Angular:如何將一個索引變數從自定義指令共享到另一個指令?
我正在嘗試在兩個 自訂指令之間共享一個索引變數:ngLoop 和 ngDN。
這是 ngLoop 的程式碼:
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[ngLoop]'
})
export class NgLoopDirective {
@Input() set ngLoop(iter_count: number) {
this.container.clear();
for (let i=0; i<iter_count; i++) {
this.container.createEmbeddedView(this.template);
}
}
constructor(private template: TemplateRef<any>,
private container: ViewContainerRef) {}
}
這是 ngDN 的代碼:
import { Directive, Input, ElementRef, Renderer2 } from '@angular/core';
@Directive({
selector: '[ngDN]'
})
export class NgDNDirective {
@Input() set ngDN(dn: number) {
this.renderer.setAttribute(this.elRef, 'data-num', dn.toString());
}
constructor(private elRef: ElementRef, private renderer: Renderer2) {}
}
問題:
現在,無論何時我嘗試看看下面 HTML 代碼的效果如何
<div *ngLoop="products.categories.length; let i = index">
<a href="#"
[ngDN]="i"></a>
</div>
我收到一個錯誤訊息說:
錯誤 TypeError:無法讀取未定義的屬性 'toString' 於 NgDNDirective.set [作為 ngDN] (ng-dn.directive.ts:9) 於 updateProp (core.es5.js:11102) 於 checkAndUpdateDirectiveInline (core.es5.js:10794) 於 checkAndUpdateNodeInline (core.es5.js:12332) 於 checkAndUpdateNode (core.es5.js:12271) 於 debugCheckAndUpdateNode (core.es5.js:13132) 於 debugCheckDirectivesFn (core.es5.js:13073) 於 Object.eval [作為 updateDirectives] (HomeComponent.html:38) 於 Object.debugUpdateDirectives [作為 updateDirectives] (core.es5.js:13058) 於 checkAndUpdateView (core.es5.js:12238)
由此我明白,索引變量 i 並未正確共享。
共享索引變數的正確方式是什麼?
答案#1
你想要達到的語法的去糖形式如下。
<!-- sugared -->
<div *ngLoop="10; let i = index">
<a href="#" [ngDN]="i"></a>
</div>
<!-- desugared -->
<ng-template [ngLoop]="10" let-i="index">
<div>
<a href="#" [ngDN]="i"></a>
</div>
</ng-template>
《code>let-i="index" 被稱為 上下文。你可以透過將一個物件作為 createEmbeddedView 的第二個參數來設定上下文。
也就是,在 for 迴圈中,你執行以下操作。
for (let i = 0; i < iter_count; i++) {
this.container.createEmbeddedView(this.template, {
index: i,
});
}
這意味著變數 index 將可在 ng-template 中使用。通過說 let-i="index",你將該模板的 index 值分配給一個本地變數 i,該變數僅在模板中的 ng-template 內可用。
這裡有一個 示範。打開控制台,你就會看到數字。
不過你會遇到渲染器的問題,因為當輸入的 setter 被呼叫時,該元素尚未可用於樣式設定。你需要將它延後到 AfterViewInit。但是你可以先 console.log 並註解掉你的渲染器方法,以確認上面的確是有效的。
