Angular:如何将自定义指令中的索引变量共享给另一个?

时间:2017-08-29 17:44:47

标签: javascript angular typescript angular2-directives

我正在尝试在两个自定义指令之间共享一个索引变量:ngLoopngDN

这是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)       at checkAndUpdateDirectiveInline(core.es5.js:10794)       at checkAndUpdateNodeInline(core.es5.js:12332)       at checkAndUpdateNode(core.es5.js:12271)       在debugCheckAndUpdateNode(core.es5.js:13132)       在debugCheckDirectivesFn(core.es5.js:13073)       在Object.eval [as updateDirectives](HomeComponent.html:38)       at Object.debugUpdateDirectives [as updateDirectives](core.es5.js:13058)       在checkAndUpdateView(core.es5.js:12238)

我从中了解到索引变量i未正确共享。

分享索引变量的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

您希望实现的语法形式如下。

<!-- 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>

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内可用。

A demo is here。打开控制台,你会看到数字。

但是渲染器会遇到问题,因为在调用输入的setter时,该元素尚不可用于样式化。您需要将其推迟到AfterViewInit。但是你现在可以console.log并注释掉你的渲染器方法,看看上面确实有效。