结构指令 - ngTemplateContextGuard 不起作用

问题描述 投票:0回答:1

我构建了一个数据表组件,其中使用结构指令来传递 rowTemplate:

<bs-datatable [data]="artists">
  <tr *bsRowTemplate="let artist">
    <td class="text-nowrap">{{ artist.name }}</td>
    <td class="text-nowrap">{{ artist.yearStarted }}</td>
    <td class="text-nowrap">{{ artist.yearQuit }}</td>
  </tr>
</bs-datatable>

我试图在自定义结构指令中提供类型推断,因此结构指令的通用类型应该从父组件推断出来。 根据文档,您应该能够简单地实现一个

ngTemplateContextGuard

@Component({ ... })
export class DatatableComponent<TData> {
  @Input() data: TData[] = [];
}

@Directive({ selector: '[appDatatableRow]' })
export class DatatableRowDirective<TData> {
  constructor(public datatable: DatatableComponent<TData>, public template: TemplateRef<TData>) { }

  static ngTemplateContextGuard<TData>(dir: DatatableRowDirective<TData>, ctx: unknown)
    : ctx is DatatableRowContext<TData> {
      return true;
    }
}

组件上的类型推断按预期工作:

但是我无法获得结构指令来推断这个泛型类型:

目标显然是在 VS Code 中推断出

$implicit
变量:

为什么这没有像我预期的那样工作?我还缺少什么?我希望结构指令能够推断父数据表的通用类型。

类似文章/讨论:

angular type-inference ngtemplateoutlet angular-structural-directive template-context
1个回答
0
投票

我最终使用了结构指令的

of
表示法:

@Directive({ selector: '[bsRowTemplate]' })
export class BsRowTemplateDirective<TData> {

  constructor(private datatableComponent: BsDatatableComponent<TData>, templateRef: TemplateRef<BsRowTemplateContext<TData>>) {
    this.datatableComponent.rowTemplate = templateRef;
  }

  @Input() set bsRowTemplateOf(value: PaginationResponse<TData> | undefined) {
    this.datatableComponent.data = value;
  }
  
  public static ngTemplateContextGuard<TData>(
    dir: BsRowTemplateDirective<TData>,
    ctx: any
  ): ctx is BsRowTemplateContext<Exclude<TData, false | 0 | '' | null | undefined>> {
    return true;
  }
}

export class BsRowTemplateContext<TData = unknown> {
  public $implicit: TData = null!;
}

数据表

@Component({
  selector: 'bs-datatable',
  ...
})
export class BsDatatableComponent<TData> {
  ...

  rowTemplate?: TemplateRef<BsRowTemplateContext<TData>>;
  data?: PaginationResponse<TData>;
}

使用方法

<bs-datatable #tabel [(settings)]="settings" (settingsChange)="loadArtists()">
  <div *bsDatatableColumn="'Name'; sortable: true">
    1. Artist
  </div>
  <div *bsDatatableColumn="'YearStarted'; sortable: true">
    2. Year started
  </div>
  <div *bsDatatableColumn="'YearQuit'; sortable: true">
    3. Year quit
  </div>

  <tr *bsRowTemplate="let artist of artists">
    <td class="text-nowrap">{{ artist.name }}</td>
    <td class="text-nowrap">{{ artist.yearStarted }}</td>
    <td class="text-nowrap">{{ artist.yearQuit }}</td>
  </tr>
</bs-datatable>
© www.soinside.com 2019 - 2024. All rights reserved.