4

Lets say we have a angular component with selector "grid"?

@Component({
  selector: 'grid',
  template: '<div>This is a grid.</div>',
  styleUrls: ['./grid.component.scss']
})

Now when we use this grid inside another component, we do the following.

    <p>This is another component.</p>
    <div>
    <grid></grid>
    <grid></grid>
    <grid></grid>
    <grid></grid>
    </div>

When this is finally rendered. The html looks like following.

<p>This is another component.</p>
<div>
<grid><div>This is a grid.</div></grid>
<grid><div>This is a grid.</div></grid>
<grid><div>This is a grid.</div></grid>
<grid><div>This is a grid.</div></grid>
</div>

Now, I don't want a grid tag here. Instead I want just the following.

<p>This is another component.</p>
<div>
<div>This is a grid.</div>
<div>This is a grid.</div>
<div>This is a grid.</div>
<div>This is a grid.</div>
</div>

How do I do it?

2
  • Even though you could do this with javascript (find an element, take all its children, remove it, and place the children in the parent of the removed element) I don't think it's possible, or desirable in Angular. I don't see how Angular could keep track of that component. If what you want is to avoid the repetition of elements, simply don't place a "div" inside and style the host element (grid) directly with :host Commented Jan 8, 2019 at 15:28
  • Are you trying to clone the div? Commented Jan 9, 2019 at 5:20

3 Answers 3

4

You use an attribute selector when you don't want to use a DOM tag.

@Component({
  selector: '[grid]',
  template: '<div>This is a grid.</div>',
  styleUrls: ['./grid.component.scss']
})

Then in the template:

<p>This is another component.</p>
<div>
<div grid></div>
</div>

Which becomes this after rendering:

<p>This is another component.</p>
<div>
<div grid><div>This is a grid.</div></div>
</div>

This is generally how you use components inside a <table> structure. For example; you might want to apply a component to a <td> element.

If you need structural HTML elements inside your component, but do not want them part of the rendered HTML, then you use a <ng-container>. This is a special DOM element that is part of the component, but not part of the DOM rendered result.

@Component({
  selector: '[grid]',
  template: '<ng-container>This is a grid.</ng-container>',
  styleUrls: ['./grid.component.scss']
})

Which becomes this after rendering:

<p>This is another component.</p>
<div>
<div grid>This is a grid.</div>
</div>

You can use <ng-container> to apply structural directives like *ngIf to the outer parts of HTML without having to add unwanted HTML.

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

11 Comments

as a side note, if you want to force developers to use a div for this component, you can write : selector: 'div[grid]'
I edited my question. I don't want to use attribute selector. I want my output to look exactly like above.
@coolswastik you don't want the div to have grid as a property ? If so, why ?
If I use grid as a property . It will render following html. <p>This is another component.</p> <div> <div ><div>This is a grid.</div></div> </div> But. I want following html. <p>This is another component.</p> <div> <div>This is a grid.</div> </div>
@coolswastik in your grid template, remove your <div> element ! :)
|
1

You can use attribute selector

<p>This is another component.</p>
<div>
<div grid></div>
</div>

Comments

0

This can be possible with ViewContainerRef Suppose you have component A

@Component({
 selector: 'a-comp',
  template: `
  <span>I am A component</span>`,
   })
  export class AComponent {
  }

And then register it with in the declarations and entryComponents in app module

@NgModule({
 imports: [BrowserModule],
 declarations: [AppComponent,       AComponent],
 entryComponents: [AComponent],
  bootstrap: [AppComponent]
   })
   export class AppModule {
   }

And then in the parent App component we put the code that creates A component instance and inserts it

@Component({
 moduleId: module.id,
 selector: 'my-app',
  template: `
  <h1>I am parent App component</h1>
  <div class="insert-a-component-    inside">
      <ng-container #vc></ng-container>
      </div>
     `,
     })
    export class AppComponent {
     @ViewChild('vc', {read:        ViewContainerRef}) vc: ViewContainerRef;

     constructor(private r:       ComponentFactoryResolver) {}

     ngAfterViewInit() {
     const factory =    this.r.resolveComponentFactory(AComponent);
     this.vc.createComponent(factory);
     }
     }

Hope this will help

1 Comment

This introduced an additional div component for ng-container.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.