Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I Create Nested Angular Component HTML Selectors?

Updated: Per Thierry Templier's response:

Below is essentially what I want to do, but unfortunately the inner components aren't rendering. Is there a way to nest components via their HTML selectors like so?

<custom-menu-bar-component (onCustomEvent)="handleEvent($event)">
    <custom-button-component></custom-button-component>
    <custom-dropdown-component></custom-dropdown-component>
</custom-menu-bar-component>

In my chrome debugger, I see only the outer component being rendered:

<custom-menu-bar-component>
    <div class="row">
        ** Nothing here, where my two inner components should be :(
    </div>
</custom-menu-bar-component>

And my components look like this:

CustomMenuBarComponent.ts:

import {Component} from 'angular2/core'
import {CustomButtonComponent} from './CustomButtonComponent'
import {CustomDropdownComponent} from './CustomDropdownComponent'

@Component({
    selector: 'custom-menu-bar-component',
    directives: [CustomButtonComponent, CustomDropdownComponent],
    template: `
        <div class="row"></div>
    `
})
export class CustomMenuBarComponent {
}

CustomButtonComponent.ts:

import {Component, EventEmitter} from 'angular2/core'
import {CustomEvent} from './CustomEvent'

@Component({
    selector: 'custom-button-component',
    outputs: ['onCustomEvent'],
    template: `
        <button type="button" class="btn btn-light-gray" (click)="onItemClick()">
        <i class="glyphicon icon-recent_activity dark-green"></i>Button</button>
    `
})
export class CustomButtonComponent {
    onCustomEvent: EventEmitter<CustomEvent> = new EventEmitter();
    onItemClick(): void {
        this.onCustomEvent.emit(new CustomEvent("Button Component Clicked"));
    }
}

CustomDropdownComponent is nearly identical to the CustomButtonComponent, but with different text. I'm just trying to get this very simple example working before I start making these components more useful and reusable.

Is this kind of approach possible? I'm trying to make it easy for others to take these components and create more of my custom menu bars with ease and simplicity.

like image 336
SnoopDougg Avatar asked Mar 30 '16 15:03

SnoopDougg


People also ask

Can we create nested component in Angular?

Angular allows us to have a different child, or nested component, which is the same component we normally use in an Angular application. The difference between them is that this child component contains the logic which can be used into the parent component as a single unit.

How can I use one component HTML in another component in Angular 8?

if you want to insert HTML elements or other components in a component, then you do that using the concept of content projection. In Angular, you achieve content projection using < ng-content >< /ng-content >. You can make reusable components and scalable applications by properly using content projection.

Can a component have multiple templates Angular?

You can simply extend your base component and overwrite the template. This allows you to have different components with the exact same functionality, but different templates. Save this answer.


2 Answers

Not sure what your question is about but

<custom-menu-bar-component (onCustomEvent)="handleEvent($event)">
    <custom-button-component></custom-button-component>
    <custom-dropdown-component></custom-dropdown-component>
</custom-menu-bar-component>

requires <ng-content></ng-content> in the template of CustomMenuBarComponent

A bit of documentation can be found in https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#aftercontent I had expected a bit more this was all I found.

http://blog.thoughtram.io/angular/2015/06/29/shadow-dom-strategies-in-angular2.html might contain some helpful information as well.

Update

Moving (onCustomEvent)="handleEvent($event)" to the <custom-button-component></custom-button-component> element should do what you want. Events from EventEmitter don't bubble.

like image 137
Günter Zöchbauer Avatar answered Oct 11 '22 00:10

Günter Zöchbauer


In fact you have the error because you don't instantiate your EventEmitter in the CustomButtonComponent component:

@Component({
  (...)
})
export class CustomButtonComponent {
  onCustomEvent: EventEmitter<CustomEvent> = new EventEmitter(); // <-----
  (...)
}

Otherwise your code seems correct.

Update

You need to use ng-content to include your sub components into the CustomMenuBarComponent one.

@Component({
  selector: 'custom-menu-bar-component',
  directives: [CustomButtonComponent, CustomDropdownComponent],
  template: `
    <div class="row">
      <ng-content></ng-content>
    </div>
  `
})
export class CustomMenuBarComponent {
}
like image 35
Thierry Templier Avatar answered Oct 11 '22 00:10

Thierry Templier