Reputation: 133
I've just begun learning Angular 2, and this is my first ever Stack Overflow question, so here goes...
I have an outer component with two nested inner components. I have a button in InnerComponent1
that, when clicked, fires an event that the outer component catches, which then passes the value (always true) into InnerComponent2
. InnerComponent2
is displayed (*ngIf) based on that value.
It works.
Buuuut.. InnerComponent2
has a button that, when clicked, makes that value false, which hides the component.
That works too.
But once I've hidden InnerComponent2
, the button in InnerComponent1
that displays InnerComponent2
no longer works. I'm not seeing any errors and I have confirmed that the outer component is still receiving the events.
Here's a plnkr that shows the scenario: http://plnkr.co/edit/X5YnNVm0dpFwA4ddv4u7?p=preview
Any thoughts?
Thanks very much.
Outer component
//our root app component
import {Component} from 'angular2/core';
import {Inner1Component} from 'src/inner1';
import {Inner2Component} from 'src/inner2';
@Component({
selector: 'my-app',
providers: [],
template: `
<p>OuterComponent</p>
<inner1 (show2)="show2Clicked = $event"></inner1>
<inner2 [showMe]="show2Clicked"></inner2>
`,
directives: [Inner1Component, Inner2Component]
})
export class App {
show2Clicked: boolean;
}
InnerComponent1
import {Component, EventEmitter, Output} from 'angular2/core'
@Component({
selector: 'inner1',
providers: [],
template: `
<p>inner1</p>
<button (click)="showInner2()">Show inner2</button>
`,
directives: []
})
export class Inner1Component {
@Output() show2 = new EventEmitter<boolean>();
showInner2() {
this.show2.emit(true);
}
}
InnerComponent2
import {Component, Input} from 'angular2/core'
@Component({
selector: 'inner2',
providers: [],
template: `
<div *ngIf="showMe">
<p>Inner2</p>
<button (click)="showMe = false">Cancel</button>
</div>
`,
directives: []
})
export class Inner2Component {
@Input() showMe: boolean;
}
Upvotes: 12
Views: 11820
Reputation: 11
I had the same problem, switching a form upon clicking a button from sibling component. My solution was to use a common service.
so in component 1 :
<button (click)="showMessageForm()" >
showForm = true;
showMessageForm() {
this.messageService.switchMessageForm(this.showForm);
this.showForm = !this.showForm;
}
in service :
switchMessageFormEvent = new EventEmitter<boolean>();
switchMessageForm(bSwitch:boolean) {
this.switchMessageFormEvent.emit(bSwitch);
}
in component 2 :
ngOnInit() {
this.messageService.switchMessageFormEvent.subscribe(
(bSwitch: boolean) => {
if(bSwitch) {
$('.message-input').slideDown("normal");
}else {
this.myForm.reset();
$('.message-input').slideUp("normal");
}
}
);
}
Upvotes: 1
Reputation: 657288
The showMe
and shwo2Clicked
values get out of sync.
I added and EventEmitter
to <inner2>
and changed
<inner2 [showMe]="show2Clicked"></inner2>
to
<inner2 [(showMe)]="show2Clicked"></inner2>
I guess it's now working as you expect
http://plnkr.co/edit/tXzr3XgTrgMWMVzAw8d7?p=preview
update
The binding [showMe]
works only in one direction. When show2Clicked
is set to true, showMe
will be set to true as well. Cancel sets showMe
back to false. If then show2Clicked
is set to true
again, nothing happens because it is already true
and showMe
isn't updated. With the EventEmitter
and two-way shorthand binding [(showMe)]
, show2Clicked
is also set to false
when showMe
is set to false
and setting it to true
is actually a change that is propagated down though the binding.
[(showMe)]="show2Clicked"
is a shorthand for [showMe]="show2Clicked" (showMeChange)="show2Clicked=$event"
and the shorthand only works when the output has the same name as the input but with an additional Change
Upvotes: 10