user6039980
user6039980

Reputation: 3506

Why changing the @Input variable from within the internal component causes its failure to detect new changes from external component?

I'm trying to set the CSS class within 'EditDialogComponent' below (which is a modal view), depending on an input property called 'showMe' that is set from 'AppComponent':

  1. HTML Code:
    <div [ngClass]="showMe? 'ui active modal': 'ui modal'">
      <i class="close icon"></i>
      <div class="header">
        Edit
      </div>
      <div class="actions">
        <div (click)="cancel()" class="ui black deny button">
          Cancel
        </div>
        <div class="ui positive right labeled icon button">
          OK
          <i class="checkmark icon"></i>
        </div>
      </div>
    </div>

2. TypeScript Code:

import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';

@Component({
  selector: 'edit-dialog',
  templateUrl: './edit-dialog.component.html',
  styleUrls: ['./edit-dialog.component.css']
})
export class EditDialogComponent implements OnInit {

  _showMe: boolean

  @Input() subject: string

  @Input() set showMe(value: boolean) {
    this._showMe = value
    window.alert('Trying to show modal')
  }

  get showMe() : boolean {
    return this._showMe
  }

  cancel() {
    this._showMe = false
  }

  constructor() { }

  ngOnInit() {
  }

}

Below is the code used to include 'EditDialogComponent' into 'AppComponent':

  1. HTML code:
        <button (click)='edit()'>Edit</button>

    <edit-dialog [showMe]="show_edit_modal" subject='foobar'></edit-dialog>
  1. TypeScript code:
    edit() {
        window.alert('Trying to show modal')
        this.show_edit_modal = true }

The problem is after the showMe @Input() gets changed from within EditDialogComponent (invoked by the click on the 'Cancel' button of the modal), it fails to detect the change of the data binding (i.e show_edit_modal) that is invoked by AppComponent.edit() (that displays "Trying to show modal" whenever I click on the Edit button of AppComponent)), since the alert from EditDialogComponent.ngOnChanges() stops showing.

Why changing the @Input variable from within the internal component causes its failure to detect new changes from external component?

Upvotes: 3

Views: 2078

Answers (2)

nicowernli
nicowernli

Reputation: 3348

@Input is just a one way binding. If you want to also change values in the parent component you have to create a two ways data binding. In order to do that you have to create an output with the same name of your input (showMe in your case) + Change (eg: showMeChange: EventEmitter<any>), and emit in your showMe setter.

In your parent component now you can use this like ngModel.

<edit-dialog [(showMe)]="show_edit_modal" subject='foobar'></edit-dialog>

I've created a full example here: https://stackblitz.com/edit/angular-c83djz

Upvotes: 2

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657048

This is working as intended. @Input() doesn't cause changes to be detected.

showMe="{{show_edit_modal}}"

is what Angulars change detection checks.

Ir better

[showMe]="show_edit_modal"

to actually pass a boolean value instead of a string

What you can do is to make showMe a setter

_showMe:boolean;
@Input() set showMe(val: boolean) {
  this._showMe = val;
  window.alert('Trying to show modal')
}

get showMe() : boolean {
  return this._showMe;
}

Upvotes: 1

Related Questions