Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove extra wrapping elements in the rendered HTML?

I started learning angular 5 3 days ago so I'm quite new at it. I also use angularJS and React to develop applications and I think I don't understand how angular 5 components fully work. If I create for example a custom button that has a custom text inside (I'm not saying this should be done this way but it's a simple example that shows my point) like this:

<app-button>
  <app-text>
    My Text
  </app-text>
</app-button>

The rendered DOM results in:

<app-button>
  <button>
    <app-text>
      <span>
        My Text
      </span>
    </app-text>
  </button>
</app-button>

which is unreadable, I wanted to know if there's a way to remove this wrapping elements and just place the components layout replacing the tags resulting in the following structure:

<button>
  <span>
    My Text
  </span>
</button>

If there's no way of removing them what are your suggestions? thanks!

like image 895
SKOLZ Avatar asked Mar 21 '18 17:03

SKOLZ


People also ask

How to remove wrapper elements but keep text content as it is?

How to remove wrapper elements but keep text content as it is using jQuery? jQuery provide several methods for performing this operation such as wrap (), wrapAll (), unwrap (). Using jQuery wrap () to wrap specified HTML elements around each selected element. Element :- It is a mandatory parameter. Function (index) It is an optional parameter.

How to wrap specified HTML elements around selected element using jQuery?

Using jQuery wrap () to wrap specified HTML elements around each selected element. Element :- It is a mandatory parameter. Function (index) It is an optional parameter. This example will demostrate you how use wrap method to selected html elements. Wrap elements inside a div using jQuery Wrap method. Hello Programmers!

How to disable word wrapping in HTML?

In this snippet, we’re going to demonstrate how you can disable word wrapping in HTML. Actually, this can be done with a few steps using some CSS properties. To prevent the text from wrapping, you can use the CSS white-space property with the “nowrap” or “pre” value. In this snippet, you can see examples with both of them.

How do you wrap an element in a tag?

Think of the wrapper element as a <strong>, <span>, <div> or whatever you need to wrap something in. Then think of the el tag as the thing that you need to put inside that <strong> tag. The function verifies that this is an element and that it has a parentNode.


2 Answers

Angular components are directives with templates. According to this:

Directive configuration @Directive({ property1: value1, ... })

selector: '.cool-button:not(a)' Specifies a CSS selector that identifies this directive within a template. Supported selectors include element, [attribute], .class, and :not().

So component selectors can be also attribute selectors. For your example, instead of writing this:

parent.component.html:

<app-button>
  <app-text>
    My Text
  </app-text>
</app-button>

write this:

parent.component.html:

<button app-button>
    <span app-text>My Text</span>
</button>

where :

app-button.component.ts

...  
  selector: '[app-button]',
  template: `<ng-content></ng-content>
...

app-text.component.ts

...
  selector: '[app-text]',
  template: `<ng-content></ng-content>`
...

this would be rendered as you expected:

enter image description here

Update after your comment about styling those buttons:

To style the buttons from inside the button component, and set class in parent component, use :host-context pseudo-class. It is not deprecated and works well

button.component.css

  :host-context(.button-1)  {
    background: red;
  }
  :host-context(.button-2)  {
      background: blue;
  }

app.component.html

<button app-button class="button-1">
    <span app-text>My Text</span>
</button>

<button app-button class="button-2">
    <span app-text>My Text</span>
</button>

Here is the DEMO

like image 119
Vega Avatar answered Oct 21 '22 09:10

Vega


I had a similar issue. I'll provide my solution in case someone else has the same problem.

My component should be able to be used either within other components or as a route from <router-outlet></router-outlet>. When I used the selector as an attribute [my-component] things worked perfectly provided it was used within other components. But when created by <router-outlet></router-outlet> a <div> were created automatically.

To avoid that, we can simply use multiple selectors, and consider that the selectors can be combined.

Consider this: I want my component to use the attribute my-component and if it ever should be created by the <router-outlet></router-outlet> it should be wrapped in a <section></section>. To achieve this simply use:

@Component(
    selector: 'section[my-component], my-component',
    ...
)

The result will be, if used inside another tag:

<whatevertag my-component>
     ... component content ...
</whatertag>

If used as a route:

<section my-component>
     ... component content ...
</section>
like image 28
ndvo Avatar answered Oct 21 '22 11:10

ndvo