Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 : render a component without its wrapping tag

People also ask

Can we create component without selector?

As you can see, in this view's @Component() meta-data, there is no "selector" property. With routable components, this isn't required. But, it can be used.

What is ViewContainerRef?

ViewContainerRef represents a container where one or more views can be attached. The first thing to mention here is that any DOM element can be used as a view container. What's interesting is that Angular doesn't insert views inside the element, but appends them after the element bound to ViewContainer .

What is Componentref in Angular?

Represents a component created by a ComponentFactory . Provides access to the component instance and related objects, and provides the means of destroying the instance.

What is the role of the attribute selector in Angular component?

What is a Selector in Angular? A selector is one of the properties of the object that we use along with the component configuration. A selector is used to identify each component uniquely into the component tree, and it also defines how the current component is represented in the HTML DOM.


You can use attribute selectors

@Component({
  selector: '[myTd]'
  ...
})

and then use it like

<td myTd></td>

You need "ViewContainerRef" and inside my-result component do something like this:

html:

<ng-template #template>
    <tr>
       <td>Lisa</td>
       <td>333</td>
    </tr>
 </ng-template>

ts:

@ViewChild('template') template;


  constructor(
    private viewContainerRef: ViewContainerRef
  ) { }

  ngOnInit() {
    this.viewContainerRef.createEmbeddedView(this.template);
  }

you can try use the new css display: contents

here's my toolbar scss:

:host {
  display: contents;
}

:host-context(.is-mobile) .toolbar {
  position: fixed;
  /* Make sure the toolbar will stay on top of the content as it scrolls past. */
  z-index: 2;
}

h1.app-name {
  margin-left: 8px;
}

and the html:

<mat-toolbar color="primary" class="toolbar">
  <button mat-icon-button (click)="toggle.emit()">
    <mat-icon>menu</mat-icon>
  </button>
  <img src="/assets/icons/favicon.png">
  <h1 class="app-name">@robertking Dashboard</h1>
</mat-toolbar>

and in use:

<navigation-toolbar (toggle)="snav.toggle()"></navigation-toolbar>

Attribute selectors are the best way to solve this issue.

So in your case:

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Time</th>
    </tr>
  </thead>
  <tbody my-results>
  </tbody>
</table>

my-results ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'my-results, [my-results]',
  templateUrl: './my-results.component.html',
  styleUrls: ['./my-results.component.css']
})
export class MyResultsComponent implements OnInit {

  entries: Array<any> = [
    { name: 'Entry One', time: '10:00'},
    { name: 'Entry Two', time: '10:05 '},
    { name: 'Entry Three', time: '10:10'},
  ];

  constructor() { }

  ngOnInit() {
  }

}

my-results html

  <tr my-result [entry]="entry" *ngFor="let entry of entries"><tr>

my-result ts

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: '[my-result]',
  templateUrl: './my-result.component.html',
  styleUrls: ['./my-result.component.css']
})
export class MyResultComponent implements OnInit {

  @Input() entry: any;

  constructor() { }

  ngOnInit() {
  }

}

my-result html

  <td>{{ entry.name }}</td>
  <td>{{ entry.time }}</td>

See working stackblitz: https://stackblitz.com/edit/angular-xbbegx


Use this directive on your element

@Directive({
   selector: '[remove-wrapper]'
})
export class RemoveWrapperDirective {
   constructor(private el: ElementRef) {
       const parentElement = el.nativeElement.parentElement;
       const element = el.nativeElement;
       parentElement.removeChild(element);
       parentElement.parentNode.insertBefore(element, parentElement.nextSibling);
       parentElement.parentNode.removeChild(parentElement);
   }
}

Example usage:

<div class="card" remove-wrapper>
   This is my card component
</div>

and in the parent html you call card element as usual, for example:

<div class="cards-container">
   <card></card>
</div>

The output will be:

<div class="cards-container">
   <div class="card" remove-wrapper>
      This is my card component
   </div>
</div>

Another option nowadays is the ContribNgHostModule made available from the @angular-contrib/common package.

After importing the module you can add host: { ngNoHost: '' } to your @Component decorator and no wrapping element will be rendered.