skip to Main Content

I’m coming from a React background. In React, when I create a custom component and include it in a page, the HTML from the component is rendered as expected.

<div> Hello World </div>

Now I’m getting into Angular and I’ve discovered that a custom component called my-custom-component renders an extra wrapper tag around the component.

<my-custom-component>
   <div> Hello World </div>
</my-custom-component>

I like writing semantic HTML with <section/> and <header/> and <aside/> tags and not use a bunch of unsupported tags. This just bloats the HTML in my opinion and makes the HTML hard to read.

So, what am I missing? I’ve read about this work-around on the Angular website but this seems like a hack. With Angular, did Google just decide not to care about semantic HTML anymore and just render whatever HTML tag it wants? I suspect it’s not hurting SEO because Angular is pretty popular.

2

Answers


  1. I used to have the same attitude towards custom tags/selectors as you, but when you get familiar with Angular and Web Components it turns out that these actually don’t cause any issues and it is merely a matter of getting used to it.

    There are some cases where the component element tag can cause issues. For example here in this question on Stackoverflow where the extra "wrapper tag" causes the table rendering to fail. But it could be resolved with a simple style hack.

    In modern HTML it is not illegal to use custom elements with their own element tags/selectors. Here on MDN you can read more on Web Components and more specifically Custom Elements:

    There are two types of custom elements:

    Autonomous custom elements are standalone — they don’t inherit from
    standard HTML elements. You use these on a page by literally writing
    them out as an HTML element. For example <popup-info>, or
    document.createElement("popup-info").

    Customized built-in elements inherit from basic HTML elements. To create one of these, you have to
    specify which element they extend (as implied in the examples above),
    and they are used by writing out the basic element but specifying the
    name of the custom element in the is attribute (or property). For
    example <p is="word-count">, or document.createElement("p", { is: "word-count" }).

    Angular components are autonomous custom elements which in its turn are classed extending the HTMLElement. For an Angular component you can set the element selector inside the component declaration. You could set it to any custom value, for example selector: 'my-custom-component' resulting in the tag <my-custom-component> but if you don’t declare a custom selector angular components will default to ng-component (<ng-component> in the HTML output).

    As far as I know the renderer completely ignores the component selector (what you refer to as "wrapper tag") and only cares about the content of the custom element. But you can of course add custom styling by using the element selector in your global stylesheet or alternatively by using the :host pseudo css class to add styling to the custom component from within its shadow DOM (read more on the :host selector here on MDN). In angular you do this in the component stylesheet (styleUrls) or styles array.

    Here also a nice read on Web Components in this Medium blog post.


    The "work around" you linked to is not what you thought it is. It is actually about using structural directives without adding new elements to the DOM, not about components and preventing the component tag/selector from rendering.

    I will use the example given to explain; say you have some content that needs to be rendered depending on a condition:

    <div *ngIf="condition">
      // content to render when condition is true…
    </div> 
    

    If the condition evaluates to true the content will be rendered, but it will render in the DOM wrapped in the div tag on which the structural directive *ngIf was used. To prevent this unnecessary (in many cases undesired) div element you can do:

    <ng-container *ngIf="condition">
      // content to render when condition is true…
    </ng-container> 
    

    In this last example there will be no output for the ng-container; the container will not be rendered in the DOM; the ng-container simply allows us to conditionally render its content.
    This example will probably get clear to you when you get more familiar with Angular.

    UPDATE

    A possible alternative to the element selector is an attribute selector which is commonly used for directives, but it can also be used for components.

    I will refer to the other answer from @Eliseo nicely demonstrating the difference between component selectors and attribute selectors.

    And here a nice blog post on Medium about using the attribute selector for Angular components.

    Login or Signup to reply.
  2. In Briefly:

    If you use as selector [name-of-selector] you apply to any "tag" of html -see the [ ]-. if you use as selector name-of-selector you use this selector as html tag

    @Component({
      selector: 'app-component-one',
      ...
    })
    
    //you use
    <app-component-one></app-component-one>
    

    or

    @Component({
      selector: '[app-component-one]',
      ...
    })
    
    //you use, e.g.
    <div app-component-one></div>
    

    Simple stackblitz

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search