에러 백과

제어 흐름이 콘텐츠 프로젝션을 차단함

제어 흐름 블록 안의 요소나 <ng-template>이 특정 <ng-content> 슬롯으로 투영되어야 하지만 블록에 루트 노드가 둘 이상 있어서 투영되지 않습니다.

import {Component} from '@angular/core';

@Component({
  selector: 'app-card',
  template: `
    <ng-content select="[card-title]" />
    <ng-content />
  `,
})
class Card {}

@Component({
  imports: [Card],
  // NG8011: <h2 card-title> is not projected into the "[card-title]" slot because the @if
  // block has two root nodes (the h2 and the p).
  template: `
    <app-card>
      @if (showTitle) {
        <h2 card-title>Title</h2>
        <p>Subtitle</p>
      }
    </app-card>
  `,
})
class MyComponent {
  showTitle = true;
}

오류 디버깅하기

제어 흐름 블록은 적용된 요소를 투영하는 *ngIf와 *ngFor의 콘텐츠 프로젝션 동작을 재현합니다. 이는 블록에 루트 노드가 하나일 때만 가능합니다. 루트 노드가 둘 이상이면 Angular가 요소를 사용해 슬롯을 선택할 수 없으므로 <h2 card-title>이 [card-title] 슬롯 대신 Card의 기본 <ng-content /> 슬롯에 들어갑니다.

텍스트도 루트 노드로 취급하므로 투영할 요소 옆에 불필요한 텍스트 한 줄이 있어도 같은 문제가 발생합니다. 블록을 포함하는 컴포넌트가 preserveWhitespaces: true를 설정했다면 공백도 루트 노드에 포함됩니다.

오류를 해결하려면 다음 방법 중 하나를 선택하세요.

  • ngProjectAs를 사용하는 <ng-container>로 콘텐츠를 감싸서 슬롯의 셀렉터와 일치시키세요. 컨테이너 안의 모든 콘텐츠가 해당 슬롯에 투영됩니다.
    @Component({
      imports: [Card],
      template: `
        <app-card>
          @if (showTitle) {
            <ng-container ngProjectAs="[card-title]">
              <h2>Title</h2>
              <p>Subtitle</p>
            </ng-container>
          }
        </app-card>
      `,
    })
    class MyComponent {
      showTitle = true;
    }
  • 콘텐츠를 여러 블록으로 나누어 각 블록의 루트에 투영할 수 있는 노드가 하나만 있도록 하세요.
    @Component({
      imports: [Card],
      template: `
        <app-card>
          @if (showTitle) {
            <h2 card-title>Title</h2>
          }
          @if (showTitle) {
            <p>Subtitle</p>
          }
        </app-card>
      `,
    })
    class MyComponent {
      showTitle = true;
    }