Nelle
Nelle

Reputation: 11

ngOnChanges() does not pick up updated Boolean @Input value from Parent Component

I needed to emit a dropdown toggle value to a child component, but it won't get picked up by ngOnChanges detects when the dropdown toggle emits true, but doesn't detect when it emits false.

ChildComponent

export class ChildComponent implements OnInit, OnChanges, OnDestroy {

  @Input() dropdownToggle!: boolean;

}
  
ngOnChanges(changes: SimpleChanges): void {
    if (changes['dropdownToggle']) {
      const currentValue = changes['dropdownToggle'].currentValue;
      console.log('ChildComponent ~ toggleDropdown value:', currentValue);
    }

ParentComponent

export class ParentComponent implements OnInit, OnChanges {

  @Output() dropdownToggle = new EventEmitter<boolean>();

  showDropdown = false;
}

  ngOnInit(): void {
  @HostListener('document:click', ['$event']) checkExternalClick($event: Event) {
    if (!this._elementRef.nativeElement.contains($event.target)) {
      if (this.showDropdown) {
        this.toggleDropdown();
      }
    } else {
      this.showDropdown = true;
    }
  }

  toggleDropdown() {
    this.showDropdown = !this.showDropdown;
    this.dropdownToggle.emit(this.showDropdown);
    console.log('ParentComponent ~ toggleDropdown value:', this.showDropdown);
  }

Made sure to properly bind event in the ParentComponent HTML:

  <div class="dropdown-hover" *ngIf="showDropdown">

    <div class="dropdown-value" (click)="toggleDropdown()">

      <input class="select" [value]="selected" (focus)="toggleDropdown()" />

    </div>

    <div class="dropdown-content">

      <hr class="divider" />

      <app-child-component

        [dropdownToggle]="showDropdown"

      ></app-child-component>

    </div>

  </div>

Result still the same:

enter image description here

Upvotes: 0

Views: 68

Answers (1)

Get Off My Lawn
Get Off My Lawn

Reputation: 36351

The easier way to do this is by injecting the parent into the child component: constructor(protected parent: Parent). From there you can access the parent component's properties/functions.

This will be easier to maintain in the long run, as you don't need to manage 2+ variables that hold the same value(s).

Here is a working example

The child would look something like this:

@Component({
  selector: 'child',
  standalone: true,
  imports: [NgIf],
  template: `
   <div *ngIf="parent.showDropdown">
      <p>Dropdown Open</p>
    </div>
  `,
})
export class Child {
  constructor(protected parent: Parent) {}
}

The parent would then have the child component within it's template or as a grandchild of another component.

@Component({
  selector: 'parent',
  standalone: true,
  imports: [Child],
  template: `
    <div>
      <child />
      <button (click)="toggle()">Toggle</button>
    </div>
  `,
})
export class Parent {
  showDropdown = false;

  protected toggle() {
    this.showDropdown = !this.showDropdown;
  }
}

Upvotes: 0

Related Questions