You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular组件中多次使用ng-content并区分插槽内容?

修复Angular多ng-content插槽内容串位问题

问题出在当前的插槽实现中:用id作为ng-content的选择器存在DOM唯一性冲突,且中间组件的ng-content未指定匹配规则,导致内容被重复投影。下面是三个组件的修复代码:

1. 主组件(app-start-time-end-time)

把id选择器换成自定义slot属性,避免多实例id冲突,同时明确插槽匹配:

<div class="p-float-label">
  <p-calendar [(ngModel)]="startTimeAsDate" formControlName="startTime"
              [inputId]="'startTime_'+day+'_' + inputIndex" 
              (ngModelChange)="checkStartTimeValidity()" 
              [showTime]="true" [timeOnly]="true">
    <p-footer>
      <ng-content select="[slot='startTime']"></ng-content>
    </p-footer>
  </p-calendar>
  <label [for]="'startTime' + inputIndex">{{'startTime' | translate}}</label>
</div>

<div class="p-float-label">
  <p-calendar [(ngModel)]="endTimeAsDate" formControlName="endTime" 
              [inputId]="'endTime_'+day+'_' + inputIndex"
              (ngModelChange)="checkEndTimeValidity()" 
              [showTime]="true" [timeOnly]="true">
    <p-footer>
      <ng-content select="[slot='endTime']"></ng-content>
    </p-footer>
  </p-calendar>
  <label [for]="'endTime' + inputIndex">{{'endTime' | translate}}</label>
</div>

修改点:用slot属性替代id,既避免DOM id重复问题,也让插槽匹配逻辑更清晰。

2. 中间组件(app-week-day-time内的app-start-time-end-time)

给每个ng-content指定匹配规则,确保内容正确分发到对应插槽:

<app-start-time-end-time [footer]="footer" [day]="day" [inputIndex]="i"
                         [isMinusButtonVisible]="plusMinusButtonVisibilities[i].isMinusButtonVisible"
                         [isPlusButtonVisible]="plusMinusButtonVisibilities[i].isPlusButtonVisible"
                         (minusButtonClicked)="removeTimeValueFromArray($event)" 
                         (plusButtonClicked)="addNewTimeValueToArray()"
                         [(endTime)]="timeValues[i].endTime!" [(startTime)]="timeValues[i].startTime!">
  <ng-container slot="startTime">
    <ng-content select="[slot='startTime']"></ng-content>
  </ng-container>
  <ng-container slot="endTime">
    <ng-content select="[slot='endTime']"></ng-content>
  </ng-container>
</app-start-time-end-time>

修改点:用ng-container包裹ng-content并指定对应slot,同时通过select接收上层传入的对应内容,避免内容被重复投影。

3. 最外层组件(app-week-day-time调用)

同时提供两个插槽的独立内容,确保每个插槽都有专属内容:

<app-week-day-time [footer]="getFooterContent()" [(timeValues)]="mondayTimeValues"
                   [dayCheckboxLabel]="translate('offDay')" [day]="'monday'">
  <!-- startTime插槽内容 -->
  <span slot="startTime" class="clickToApllyStart clickable cursor-pointer text-blue-500 w-3 pl-3" 
        (click)="onApplyToAllStartTimesClicked(mondayTimeValues[0].startTime, 0)">
    Apply to All Start Times
  </span>
  <!-- endTime插槽内容,可根据需求自定义 -->
  <span slot="endTime" class="clickToApllyEnd clickable cursor-pointer text-blue-500 w-3 pl-3" 
        (click)="onApplyToAllEndTimesClicked(mondayTimeValues[0].endTime, 0)">
    Apply to All End Times
  </span>
</app-week-day-time>

修改点:给每个内容块加上对应的slot属性,让上层组件能精准匹配到对应的ng-content插槽。

核心原理

Angular的ng-content是基于内容投影的:如果没指定select,会投影所有未被匹配的内容;指定select后,只会匹配对应属性/标签的元素。之前的问题就是中间组件的两个ng-content都没加select,导致都投影了上层的所有内容,才出现串位。通过明确slot属性和匹配规则,就能实现每个插槽独立投影内容。

内容的提问来源于stack exchange,提问作者emindemirhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 02:34:52