Skip to content

Projected content in a toggled @if comes back without its children with provideNgtRenderer() #95

Open

Description

@dolanmiu

I have noticed that with provideNgtRenderer(), content projected into an @if comes back empty after the @if turns off and on again. It happens to plain DOM elements, not only Three.js ones, because the renderer wraps every component's renderer.

@Component({
  selector: 'app-slot',
  template: `@if (open()) { <ng-content /> }`,
})
export class Slot {
  readonly open = signal(true);
}

@Component({
  selector: 'app-host',
  imports: [Slot],
  template: `<app-slot><span class="glyph">G</span></app-slot>`,
})
export class Host {}

After open goes false then true again:

  • without provideNgtRenderer(): <app-slot><span class="glyph">G</span><!--container--></app-slot>
  • with provideNgtRenderer(): <app-slot><span class="glyph"></span><!--container--></app-slot>

When Angular destroys the @if's view, it also calls destroyNode on the projected <span>, though the host's view still owns it and inserts it again later. NgtRenderer2.destroyNode runs internalDestroyNode(node, this.removeChild), which calls removeChild(node, child) for each of the span's children before the owner check, so the text node is taken out of the span for good:

for (const child of rS[NgtRendererClassId.children].slice()) {
const destructionOwner = rS[NgtRendererClassId.ownedNodes] ? node : rS[NgtRendererClassId.owner];
const childOwner = child.__ngt_renderer__[NgtRendererClassId.owner];
removeChild?.(node, child);
if (destructionOwner && childOwner && childOwner !== destructionOwner) continue;
internalDestroyNode(child, removeChild);
}

I found it in an app built on AngularLynx, where a searchable select lost the icons of the items the search had hidden: Blotch-Smart-Frames/AngularLynx#380

  • angular-three 4.2.4 (the code is the same on main)
  • three 0.178.0
  • Angular 22.2.4

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions