2

I have this button, that I use in multiple places throughout my site.

Because of that, I moved it to Component. I call it GetInvolvedButtonComponent.

However, I can't use this Component right now because Angular is wrapping a special HTML tag around it. That cause issue.

How do I render the HTML straight into the section without it being wrapped in that tag?

Here's what I have thus far:

get-involved-button.component.html

<!-- TODO: This is going to route to another page called "Get Involved" --> <a class="btn btn-primary center" routerLink="/contact">Get Involved!</a> 

get-involved-button.component.ts

import { Component, OnInit } from "@angular/core"; @Component({ selector: "[get-involved-button]", templateUrl: "./get-involved-button.component.html", styleUrls: ["./get-involved-button.component.css"], }) export class GetInvolvedButtonComponent implements OnInit { constructor() {} ngOnInit(): void {} } 

When I inspect the DOM element in the developer console, this is what I see:

enter image description here

5
  • Can you post the wrapper html screenshot or code ? Commented Jul 19, 2020 at 15:11
  • 1
    If it is a component, there is no way to avoid having an html tag for the component. A workaround is to use some css that practically ignores the container element: ':host { display: contents; }` Check for compatibility. Commented Jul 19, 2020 at 15:23
  • @alou, really you can use as selector a name between [ and ] and you can applied to any html tag, e.g. a div Commented Jul 19, 2020 at 18:28
  • May I see what that looks like, for future reference? It's been literally years since I've done any Angular, and I didn't know this Commented Jul 20, 2020 at 1:04
  • @MikeWarren, he means using as component selector an actual html element, eg [div] which will practically render your component for all div tags. I don't know if that's really an option, but it would work. Commented Jul 20, 2020 at 18:22

3 Answers 3

2

The CSS solution works well, but it is not perfect:

:host { display: contents; } 

This solution say to browser that the wrapper component tag must be ignored.

But this solution do no apply the right style if it is this:

table > :not(caption) > * > * { border-bottom-width: 1px; } 

This CSS apply the border width to element in 3° descendant. For example:
tbody > tr > td

But if DOM structure contains the Angular wrapper, the 3° descendant is tr:
tbody > appMyTableRows > tr

To solve this issue I am using another solution: ng-container + ViewContainerRef.

Most complex but better solution

The solution is to draw the entire component inside a ng-template, then it will be rendered in caller component using ng-content.

How to draw component template:

<ng-template #bodyTempl> <tr> <td>This is</td> <td>the content</td> <td>of Component.</td> </tr> <tr> <td>This is</td> <td>the content</td> <td>of Component.</td> </tr> </ng-template> 

Then in Component code we must add something like this:

@ViewChild("bodyTempl") bodyTemplate: TemplateRef<any>; 

As last step, we need to change how we use the component in template:

<table> <thead> <tr> <th>head</th> <th>head</th> <th>head</th> </tr> </thead> <tbody> <tr> <td>row 1</td> <td>row 1</td> <td>row 1</td> </tr> <app-my-table-tr #childComRef></app-my-table-tr> <ng-content *ngTemplateOutlet="childComRef.bodyTemplate"></ng-content> </tbody> </table> 

The HTML result shows the "app-my-table-tr" tag like child of TBODY, but it is empty. And the content of component will be injected like sibling of the component:

<table> <thead> <tr> <th>head</th> <th>head</th> <th>head</th> </tr> </thead> <tbody> <tr> <td>row 1</td> <td>row 1</td> <td>row 1</td> </tr> <app-my-table-tr _ngcontent-...></app-my-table-tr> <tr> <td>This is</td> <td>the content</td> <td>of Component.</td> </tr> <tr> <td>This is</td> <td>the content</td> <td>of Component.</td> </tr> </tbody> </table> 

To a perfect solution, write this in CSS of Component, so the wrapper will not rendered:

:host { display: none; } 

(source: https://blog.josematos.work/how-to-render-an-angular-component-without-any-wrapping-tag-5084c84e0a62)

Sign up to request clarification or add additional context in comments.

1 Comment

you have save my life.
1

Per @alou's comment on here, I just had to

:host { display:contents } 

inside the component's CSS file, and it work.

Comments

1

For me,

:host { display: contents; } 

Works perfectly!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.