Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2: capture events from ng-content

Tags:

angular

Angular app structure:

<app><div content><a href="#" (click)="show()">click me</a></div></app>

Content component template:

<ng-content></ng-content>

Content component has public method show(), but when i click this link i get:

Error: EXCEPTION: Error during evaluation of "click"
ORIGINAL EXCEPTION: TypeError: l_context.show is not a function
ORIGINAL STACKTRACE:
anonymous/ChangeDetector_AppComponent_0.prototype.handleEventInternal@http://localhost:3000/node_modules/angular2/bundles/angular2.dev.js line 10897 > Function:207:13
AbstractChangeDetector</AbstractChangeDetector.prototype.handleEvent@http://localhost:3000/node_modules/angular2/bundles/angular2.dev.js:8788:17

Basically i want to reuse page markup and put listeners on existing dom, i don't want to create additonal templates or components. Probably i'm missing something obvious.

Planker

like image 386
kemsky Avatar asked Feb 23 '16 09:02

kemsky


People also ask

How do you style content that was projected using NG-content?

If you want to style the projected content within <ng-content>, you can do so using :host and ::ng-deep to apply styling to all nested elements within the <contact> component.

What is Contentprojection?

Content projection is a pattern in which you insert, or project, the content you want to use inside another component. For example, you could have a Card component that accepts content provided by another component.

What is Ngcontent?

The ng-content is used when we want to insert the content dynamically inside the component that helps to increase component reusability. Using ng-content we can pass content inside the component selector and when angular parses that content that appears at the place of ng-content.

What is the difference between Ng-content ng container and ng-template?

ng-container serves as a container for elements which can also accept structural directives but is not rendered to the DOM, while ng-template allows you to create template content that is not rendered until you specifically (conditionally or directly) add it to the DOM.


1 Answers

show() would resolve to the parent component of <app> and because it looks like <app> is the root component, there is no parent.

I guess the bug here is that Angular even tries to bind to the click event. I got the impression that <ng-content> isn't supported at all on the root component.

See also https://github.com/angular/angular/issues/1858 (https://github.com/angular/angular/issues/6046)

Update

<h1>Angular</h1>
<div content #contentRef>
    <ui>
        <li><a href="#" (click)="contentRef.show($event)" class="link" button>link 1</a></li>
        <li><a href="#" (click)="contentRef.show($event)" class="link" button>link 2</a></li>
        <li><a href="#" (click)="contentRef.show($event)" class="link" button>link 3</a></li>
    </ui>
</div>

bindings are resolved within the component where they are declared. In the above example I explicitly redirected the reference to the ContentComponent by creating a template variable #contentRef on the target element and referring it when defining the click handler (click)="contentRef.show($event)".

Even though the content is "passed" to another component using <ng-content> doesn't mean the scope changes. <ng-content> is only a projection - the elements are displayed at a different place is all, they are still "owned" by the component where they are added originally.

like image 144
Günter Zöchbauer Avatar answered Oct 24 '22 10:10

Günter Zöchbauer