2

In my Planning component I have the following directive where selectedPerson is an object on the service and showModal is a local boolean parameter in the Planning component:

<person-popup [person]="planningService.selectedPerson" [show]="showModal"></person-popup>

The PersonPopop component has the following simple structure:

import { Component, Input } from '@angular/core';
import { Counselor } from '../entities/counselor';
import { Person } from '../entities/person';
import { Request } from '../entities/request';


@Component({
    selector: 'person-popup',
    templateUrl: './person-popup.component.html',
    styleUrls: ['./person-popup.component.css']
})


export class PersonPopupComponent {

    @Input() person: Person;
    @Input() show: boolean;

    constructor() { }

    public displayCss() {
        return this.show ? "displayBlock" : "";
    }

    public toggleShow() {
        this.show = !this.show;
        console.log("toggleShow: ", this.show)
    }
}

The corresponding HTML view currently looks like this:

<p>{{show}}</p>
<p>{{person?.name}}</p>
<button (click)="toggleShow()">Show</button>

<div class="modal-background {{displayCss()}}" (click)="toggleShow()">
    <div class="modal-content animate">
        {{person?.name}}
    </div>
</div>

When the Planning component is initiated the show property is null. Changes of selectedPerson are always propagated to the popup component but the same is NOT true for the showModal parameter.

When showModal is first set to true in the parent it is set to true in the child component.

The child component will then set its local show property to false. After that it seems "the Input connection is lost" and all subsequent changes of showModal will not propagate to show.

Any suggestions on how to redesign this?

n00dl3
  • 21,213
  • 7
  • 66
  • 76
Jakob Lithner
  • 4,225
  • 6
  • 38
  • 59
  • Possible duplicate of [Update parent component property from child component in Angular 2](http://stackoverflow.com/questions/41464871/update-parent-component-property-from-child-component-in-angular-2) – n00dl3 Mar 31 '17 at 13:45

1 Answers1

4

You need to use two way binding if you want to propagate the changes from child to parent :

export class PersonPopupComponent {

    @Input() person: Person;
    @Input() show: boolean;
    @Ouput() showChange= new EventEmitter<boolean>();

    constructor() { }

    public displayCss() {
        return this.show ? "displayBlock" : "";
    }

    public toggleShow() {
        this.show = !this.show;
        this.showChange.emit(this.show);
        console.log("toggleShow: ", this.show)
    }
}

then in parent :

<person-popup [person]="planningService.selectedPerson" [(show)]="showModal"></person-popup>
n00dl3
  • 21,213
  • 7
  • 66
  • 76
  • Thanks for quick answer! Some follow up questions to ensure I understand: 1) You mean all I need to do is to add paranthesis in directive binding, and add corresponding output parameter with emitter? 2) Is showChange a naming convention that will automatically match the two-way binding? 3) Isn't it confusing to emit a value and also set the local parameter? Wouldn't it be enough to just call this.showChange.emit(!this.show) and let it propagate the change to the Input parameter? – Jakob Lithner Mar 31 '17 at 14:28
  • 1
    1. yes. 2. the `Change` suffix is for using `[(bananaInABox)]` notation, but you can name it `showFoo`, for example, and use `[show]="someData" (showFoo)="doSomething($event)"` note that you ca do the same with `(showChange)="doSomething($event)"` ,banana in a box is not mandatory 3. Yes I guess it is possible. – n00dl3 Mar 31 '17 at 14:36
  • For future readers I just add a reference to another post where two-way binding is performed with get/set methods. That makes it more verbose but it might be useful for some more complex cases. http://stackoverflow.com/a/39943368/1122813 – Jakob Lithner Mar 31 '17 at 14:48
  • @JakobLithner Just thought about your last "3." point. That might work, but only if you only rely on `@Input()` to get the value of that property. If you do that the two way binding becomes mandatory. – n00dl3 Apr 03 '17 at 07:56