【问题标题】:Angular 2 Parent Component Losing Input Binding from Child ComponentAngular 2父组件丢失来自子组件的输入绑定
【发布时间】:2017-08-18 20:41:44
【问题描述】:

我正在使用一个父组件,该组件引用一个在 Angular 2 中播放音频文件的子组件。最初,我向音频文件传递了一个 _audioState 的输入变量,其中包含一个字符串值“Listen”。单击音频按钮时,该值将更改为“正在播放”,然后在音频文件播放完毕后更改为“重播”。这些字符串值更改发生在音频子组件中。

当在父组件中单击具有 nextAudio 功能的按钮时,我想将 _audioState 重新分配回“Listen”,但是一旦子组件更改此值,输入绑定在父组件中不起作用。

我仍在学习 Angular 2,并不确定实现此功能的最佳方法。我很感激任何建议。我的代码如下。

父组件:

 @Component({
    selector: 'parent-component',
    template: ' <div>
                    <button (click)="nextAudio()"></button>
                    <audio-button [audioPath]="_audioPath"  
                    [audioSrc]="_audioCounter" [audioState]="_audioState">          
                    </audio-button>
                </div>',
    styleUrls: ['./parent-component.less']
})

export class ParentComponent {
 _audioPath: string = "../audio/";
 _audioCounter: number = 1;
 _audioState: string = "Listen";

  nextAudio(): void{
    this._audioCounter = this._audioCounter + 1;
    this._audioState = "Listen";
  }  
}

子组件:

@Component({
    selector: 'audio-button',
    template: '<button (click)="playSound()"><i class="fa fa-volume-up"></i>    
    {{audioState}}</button>',
    styleUrls: ['./audio-button.component.less']
})
export class AudioButtonComponent {
    @Input() audioPath: string;
    @Input() audioSrc: string;
    @Input() audioState: string;

playSound(): void {
    let sound: any = new Audio(this.audioPath + this.audioSrc + ".mp3");
    sound.play();
    this.audioState = "Playing";
    sound.addEventListener('ended', () => {
        this.audioState = "Replay";
    }, false)

    event.preventDefault();
   }
}

【问题讨论】:

    标签: angular angular2-template


    【解决方案1】:

    有几种方法可以做到这一点,包括

    1。 (推荐)使用ngrx/store

    参考文献

    Adding Redux with NgRx/Store to Angular (2+) – Part 1(Oren Farhi)

    2。 EventEmitter

    例如,

    @Component({
    selector: 'parent-component',
    template: `<div>
                    Current state : {{_audioState}}
                    <hr />
                    <audio-button [audioPath]="_audioPath"
                    [audioSrc]="_audioCounter" [audioState]="_audioState"
                    (emit-status)="updateStatus($event)"
                    >
                    </audio-button>
                </div>`
    })
    
    export class ParentComponent {
      _audioPath: string = "../audio/";
      _audioCounter: number = 1;
      _audioState: string = "Listen";
    
      nextAudio(): void{ 
        this._audioCounter = this._audioCounter + 1;
        this._audioState = "Listen";
      }
    
      private updateStatus(status:string){
        this._audioState= status;
      }
    }
    

    import { Component, OnInit, Input, Output, EventEmitter } from           '@angular/core';
    
    @Component({
       selector: 'audio-button',
       template: `<button (click)="playSound()"><i class="fa fa-volume-up"></i>
    {{audioState}}</button>`,
    })
    
    export class AudioButtonComponent {
      @Input() audioPath: string;
      @Input() audioSrc: string;
      @Input() audioState: string;
      @Output('emit-status') emitStatus = new EventEmitter<any>();
    
      
      playSound(): void {
        //...
    
        //emit data to parent
        this.emitStatus.emit("playing");
      }
    }
    

    3.ViewChild

    @Component({
       selector: 'parent-component',
       template: `<div>
                Current state : {{audioBtn.audioState}}
                <hr />
                <audio-button [audioPath]="_audioPath"
                [audioSrc]="_audioCounter" [audioState]="_audioState"
                (emit-status)="updateStatus($event)"
                >
                </audio-button>
            </div>`
    })
    
    export class ParentComponent {
        @ViewChild(AudioButtonComponent) audioBtn: AudioButtonComponent;
    }
    

    export class AudioButtonComponent {
       //...
      @Input() audioState: string;
      playSound(): void {
         //...
         this.audioState = "playing";
      }
    }
    

    结果

    【讨论】:

    • 谢谢!感谢帮助。我之前使用过 output 和 EventEmitter,但不确定是否有更好的方法。
    • 我认为状态管理最简洁的方法之一是使用ngrx/stroe。但是在不那么复杂的应用程序中,我们可以使用 EventEmitter 或 ViewChild 来完成。
    • 听起来不错。我正在考虑使用 ViewChild 但无法正确引用子组件。 ViewChild 只能在 ngAfterViewInit() 中使用吧?
    猜你喜欢
    • 2018-02-13
    • 2020-01-25
    • 1970-01-01
    • 2018-06-07
    • 2019-01-06
    • 1970-01-01
    • 2017-02-15
    • 2018-08-30
    • 2018-07-09
    相关资源
    最近更新 更多