5

My child-component looks like:

...
@Component({
    selector: '[child-component]'
    templateUrl: './child.template.html'
})
...

and my parent template like:

<span child-component [someInput]="123"></span>

now I want to render the content of my child component without the <span> container around it. I want no container at all in my parent component's template, just the content of our child-component's template.

I tried some other tags already.

  • <ng-content> (nothing rendered at all)
  • <ng-template> (Components on an embedded template:)
  • <ng-container> (Failed to execute 'appendChild' on 'Node')

Thanks in advance!

Yashwardhan Pauranik
  • 5,370
  • 5
  • 42
  • 65
sevic
  • 879
  • 11
  • 36

3 Answers3

12

Finally found a working soltion!

My child-component looks like:

@Component({
    selector: 'child-component'
    templateUrl: './child.template.html'
})
export class ChildComponent {
  @ViewChild('childComponentTemplate') childComponentTemplate: TemplateRef<any>;
}

My child template looks like:

<ng-template #childComponentTemplate>
  ... some content ...
</ng-template>

and my parent template like:

<child-component #wrapper [someInput]="123"></child-component>
<ng-container *ngTemplateOutlet='wrapper.childComponentTemplate'></ng-container>

This way there is no wrapper at all.

sevic
  • 879
  • 11
  • 36
  • 1
    Wow... in 2022 this was my only solution. I am trying to convert a react app to angular. unfortunately I love using react fragments and there is no equivalent in angular so this Hack is a life saver. Thanks a million – Fabio Delarias Apr 22 '22 at 20:54
  • I'm not really following this. Ok, maybe it won't result in any wrappers, but you will still have a mess in the dom. Once rendered, won't this result in: ... some content ... Which would still mess up things if used inside e.g. , , ... and all other components that expect specific child components – ZolaKt May 19 '22 at 07:09
  • This works a treat and while obviously not how we'd prefer to do it, get's the job done with only a couple extra lines. One thing to note is that by changing the child template property to `@ViewChild('childComponentTemplate', { static: true })` you can avoid the annoying expressionChangedAfterItHasBeenChecked issue since it won't be undefined when it loads. – JWrightII Aug 01 '22 at 23:59
6

Your use-case can be solved by using CSS only, just set child-component as display: contents,

child-component {
    display: contents;
}

As stated on display: contents documentation, this causes to appear as if the component were direct children of the element's parent.

luiscla27
  • 4,956
  • 37
  • 49
  • 3
    It is a cool trick, but it is not what op want. He want to remove the element from the DOM, not just visually. – maxisam Feb 23 '21 at 17:14
  • 1
    This answer appeals that maybe he doesn't need to remove the DOM :) the element using `display:contents` ignores itself, this is mainly useful when a wrapper element should be ignored when using CSS grid or similar layout techniques. – luiscla27 Feb 23 '21 at 19:49
1

This method can avoid ExpressionChangedAfterItHasBeenCheckedError error.

child-component:

@Component({
    selector: 'child-component'
    templateUrl: './child.template.html'
})

export class ChildComponent implements OnInit {
@ViewChild('childTemplate', {static: true}) childTemplate: TemplateRef<any>;

constructor(
      private view: ViewContainerRef
) {}

ngOnInit(): void {
    this.view.createEmbeddedView(this.currentUserTemplate);
}

}

parent-component:

<child-component></child-component>
CoTg
  • 91
  • 1
  • 6