问题
Okay so here's what I'm trying to achieve :
I have this component :
import { Component, Output, EventEmitter, OnInit } from '@angular/core';
@Component({
selector: 'like',
template: '<p>this is the like component<p>'
})
export class LikeComponent implements OnInit{
title: string = 'Like Component';
@Output() sendTitle = new EventEmitter();
ngOnInit() {
this.sendTitle.emit({title: this.title});
}
}
I want to send the title from it to the parent :
import { Component, Input } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'panel',
template: `
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">{{title}}</h2>
</div>
<div class="panel-body">
<ng-content (sendTitle) = "receiveTitle($event)"></ng-content>
</div>
</div>
`
})
export class PanelComponent {
title = 'default title';
receiveTitle(arg) {
this.title = arg.title;
console.log(arg);
}
}
Then I could reuse the PanelComponent
with every component I want to wrap in a panel :
<panel>
<like></like>
</panel>
<panel>
<another-component></another-component>
</panel>
<panel>
<exemple-component></exemple-component>
</panel>
Each time a Panel
component would be shown, it would try to get the title from the event if it exists.
It seems that this isn't working with ng-content as it is with regular parent/child component? I'm not familiar with angular 2 so I'd appreciate your feedback!
tl;dr : I want a way for a parent to know a properties from a child but the child musn't be specific (this is why I use <ng-content>
).
In brief, I don't want to do it through input
like this :
<panel [title] = "'This is the panel title of the like component'">
<like></like>
</panel>
<panel [title] = "'This is the panel title of the another-component'">
<another-component></another-component>
</panel>
回答1:
After a lot of searching, I found a solution like Sasxa's, but able to work with any child component. The key is that the "selector" for @ComponentChild
can be a string.
interface TitledComponent {
title?: string;
}
@Component({
selector: 'panel',
template: `<div class="panel">
<h2>{{title}}</h2>
<ng-content></ng-content>
</div>`
})
export class PanelComponent {
title = 'default title';
@ContentChild('titled') childComponent: TitledComponent;
ngAfterContentInit() {
if (this.childComponent)
this.title = this.childComponent.title || 'default title';
}
}
And the html would have to be
<panel>
<like #titled></like>
</panel>
<panel>
<other #titled></other>
</panel>
<panel>
<p>I don't have a title</p>
</panel>
<panel>
<like></like>
<!-- This won't be picked up -->
</panel>
回答2:
Try this:
export class PanelComponent {
title = 'default title';
@ContentChild(LikeComponent) like: LikeComponent;
ngAfterContentInit() {
this.title = this.like.title;
}
}
回答3:
If you want to use the event approach, you can use element.dispatchEvent
to create a bubbling event. EventEmitter
events don't bubble and should only be used with (xxx)
binding.
In the child component this would look like
constructor(private elRef:ElementRef, private renderer:Renderer) {}
onBlur($event) {
this.renderer.invokeElementMethod(this.elRef.nativeElement,
'dispatchEvent',
[new CustomEvent('input-blur', { bubbles: true })]);
See also my similar answer in Angular2 how to know when ANY form input field lost focus
回答4:
i think this should do it in the panel template
<h2>{{title}}</h2>
<panel class="col-xs-6 col-md-4">
<like (sendTitle)="receiveTitle($event. title)"></like>
</panel>
and set this in the component :
receiveTitle(title) {
this.title = title;
console.log(event);
}
you send Output events like you do (click) events. () means that you submit something from the html to the component, [] means you bind something from the component to the html.
hope this is what you mean !
it's not really clear why you want to use ng-content ? everytime you click, the parent title will be updated from the child component.
来源:https://stackoverflow.com/questions/37869202/angular-2-how-do-i-send-childcomponent-properties-to-parent-when-you-dont-kno