web-dev-qa-db-ja.com

Angular 6 ngFor multiple context内のngTemplateOutlet

次のコンポーネントがあるとしましょう:

@Component({
  selector: 'todo-lib',
  template: `
<li *ngFor="let todo of libService.todos">
  <div class="view">
    <label>{{todo.title}}</label>
    <ng-container *ngTemplateOutlet="incomingTemplate;context:ctx"></ng-container>
  </div>
</li>

<ng-template #incomingTemplate let-service="templateService">
<button (click)="service.removeTodo(todo)">delete</button>
</ng-template>
`,
  styles: []
})
export class TodoLibComponent implements OnInit {

  ctx = {
    templateService: this.libService
  };

TodoのリストはlibService内にあります。ロジックは関係ないので、ここでは公開しません。 「ng-template」は別のコンポーネントから挿入され、私のToDoリストに削除ボタンが追加されます。つまり、「ng-template」が提供されることを除いて、通常は削除オプションはありません。

ただし、このアプローチは次のエラーで失敗します。

message: "_v.context.todo is undefined"

「todo」はコンテキストオブジェクト 'ctx'の一部ではないため、アクセスできません。これを達成するために、私は次のようにする必要があります。

<ng-container *ngTemplateOutlet="incomingTemplate;context:{ todo: todo}">

これにより、todoオブジェクトにアクセスできますが、サービスにはアクセスできなくなります。

NgForで定義された「todo」プロパティと「ctx」プロパティで定義されたサービスに同時にアクセスできないようです。両方を達成するための解決策はありますか?

乾杯

5
Baerree

また、Angularの公式のgithubリポジトリでも言及しました。開発者による正しいアンサーは次のとおりです。

@dawidgarus:次のことができます:

<ng-container *ngTemplateOutlet="incomingTemplate;context:{ todo: todo, templateService: libService }">

加えて:

@dawidgarusの提案は良いものであり、現在のスコープでのスコープのしくみに従っていますAngular-もう一度見たいとは思いません。私が提案するのは、<ng-template>要素の代わりに<ng-container>を使用すると、生成されるコードが少なくなり、DOMなどに不要なコメントノードが作成されなくなります。

<ng-template [ngTemplateOutlet]="incomingTemplate" [ngTemplateOutletContext]="{ todo: todo, templateService: libService }">

そのため、ng-containerの代わりにng-templateを使用しました。

乾杯

2
Baerree

関数と変数を渡す方が簡単なようです。

<ng-template #incomingTemplate let-service="templateService">
<button (click)="service">delete</button>
</ng-template>

その後

<ng-container *ngTemplateOutlet="incomingTemplate; context:removeTodo(todo)"></ng-container>
1