@Input()中相同的布尔值,不会触发更改检测

时间:2019-11-08 08:38:33

标签: angular

我有一个角度应用程序,其中有一个弹出组件。我可以通过其父级或本身来控制弹出窗口的可见性。

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
  <popup [visible]="visible"></popup>
  <button (click)="onShow()">Show</button>
  <button (click)="onHide()">Hide</button>
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  public visible: boolean = false;
  public onShow(): void {
    this.visible = true;
  }
  public onHide(): void {
    this.visible = false;
  }
}

popup.component.ts

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

@Component({
  selector: 'popup',
  template: `<div *ngIf="visible">My fancy popup <button (click)="onClick()">Click to close</button></div>`,
})
export class PopupComponent  {
  @Input()
  public visible: boolean;

  public onClick(): void {
    this.visible = false;
  }
}

工作stackblitz

用例:

  • 用户可以通过单击弹出窗口中的按钮来关闭弹出窗口
  • 用户可以通过单击父级组件中的按钮来关闭弹出窗口
  • 用户可以通过单击父级组件中的按钮来显示弹出窗口

问题:

  • 单击以显示弹出窗口
  • 单击内部弹出窗口将其隐藏
  • 单击以显示弹出窗口
  • 弹出窗口没有显示

据我所知,这是因为visible内的app.component.ts成员未更改,因此PopupComponent的{​​{1}}值也未更改。知道如何解决这个问题吗?

3 个答案:

答案 0 :(得分:3)

您应将更改从子级更改为父级:

export class PopupComponent  {
  @Input()
  public visible: boolean;
  @Output() visibleChange: EventEmitter<boolean> = new EventEmitter<boolean>();

  public onClick(): void {
    this.visible = false;
    this.visibleChange.emit(this.visible);
  }
}

父母:

@Component({
  selector: 'my-app',
  template: `
  <popup [(visible)]="visible"></popup>
  <button (click)="onShow()">Show</button>
  <button (click)="onHide()">Hide</button>
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  public visible: boolean = false;
  public onShow(): void {
    this.visible = true;
  }
  public onHide(): void {
    this.visible = false;
  }
}

forked demo

答案 1 :(得分:1)

  

您可以使用Event Emitter将值从子级传递给父级

APP组件

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

        @Component({
          selector: 'popup',
          template: `<div *ngIf="visible">My fancy popup <button (click)="onClick()">Click to close</button></div>`,
        })
        export class PopupComponent  {
          @Input()
          public visible: boolean;
          @Output() close: EventEmitter<any> = new EventEmitter();

          public onClick(): void {
            this.visible = false;
            this.toggle();
          }
          toggle() {
             this.close.emit(false);
          }
        }
  

应用组件

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
  <popup [visible]="visible" (close)="onHide($event)"></popup>
  <button (click)="onShow()">Show</button>
  <button (click)="onHide()">Hide</button>
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  public visible: boolean = false;
  public onShow(): void {
    this.visible = true;
  }
  public onHide(value: boolean): void {
    console.log(value)
    if(value) {
      this.visible = value;
    } else {
          this.visible = false;
    }

  }

}

答案 2 :(得分:1)

popup.component.ts

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

@Component({
  selector: 'popup',
  template: `<div *ngIf="visible">My fancy popup <button (click)="onClick()">Click to close</button></div>`,
})
export class PopupComponent implements OnInit  {
  @Input() visible;
  @Output() visibleUpdate = new EventEmitter();
  // public visible: boolean;

  ngOnInit() {
    console.log('ngOnInit', this.visible);
  }

  public onClick(): void {
    this.visible= false;
    this.visibleUpdate.emit(this.visible);

    console.log('onClick', this.visible);
  }
}

app.component.ts

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

@Component({
  selector: 'my-app',
  template: `<popup [visible]="visible" (visibleUpdate)="visibleUpdated($event)"></popup>
    <button (click)="onShow()">Show</button>
    <button (click)="onHide()">Hide</button>`,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  public visible: boolean = false;

  public onShow(): void {
    this.visible = true;

    console.log('onShow', this.visible);
  }
  public onHide(): void {
    this.visible = false;

    console.log('onHide', this.visible);
  }

  public visibleUpdated($event): void {
    this.visible = $event;

    console.log('visibleUpdate', $event)
  }
}

如果您有任何疑问,请告诉我。