在 Angular 应用程序中将值从输入组件传递到按钮组件

Pass value from input component to button component in Angular application

我想知道如何将值从一个 Angular 组件传递到另一个 my-input.componentmy-button.component:

我正在尝试从 my-input.component.ts 接收并使用 my-button.component.ts 中的 my-button.component.html 按钮 (click)="displayReceivedValue()" 显示 @Input('name'):

import { Component, Input, OnInit } from '@angular/core';
import { MyInput } from '../../interfaces/my-input';

@Component({
  selector: 'app-my-button',
  templateUrl: './my-button.component.html',
  styleUrls: ['./my-button.component.scss'],
})
export class MyButtonComponent implements OnInit {
  @Input('name')
  public input!: MyInput;
  constructor() {}

  ngOnInit(): void {}

  async displayReceivedValue() {
    console.log('Received value: ', this.input);
  }
}

这是 Login page login.component.html 中的 <app-my-button name=""></app-my-button> 组件,来自 my-input.component.tsthis.myValue 来自 [(ngModel)]="myValue" 中的 input =29=],但我不确定如何将其传递给 name="":

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

@Component({
  selector: 'app-my-input',
  templateUrl: './my-input.component.html',
  styleUrls: ['./my-input.component.scss'],
})
export class MyInputComponent implements OnInit {
  
  public myValue: any;

  constructor() {}

  ngOnInit(): void {}
}

我也试过在 Login page 中使用 @Output()<app-my-button (inputValue)="acceptData($event)"></app-my-button> 组件来自 my-input.component.ts:

import { Component, EventEmitter, OnInit, Output } from '@angular/core';
    
    @Component({
      selector: 'app-my-input',
      templateUrl: './my-input.component.html',
      styleUrls: ['./my-input.component.scss'],
    })
    export class MyInputComponent implements OnInit {
      @Output() inputValue= new EventEmitter<string>();
        
      public myValue: any;

      constructor() {}
    
      ngOnInit(): void {
           this.inputValue.emit(this.inputValue);
      }
    }

my-button.component.ts中:

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

@Component({
  selector: 'app-my-button',
  templateUrl: './my-button.component.html',
  styleUrls: ['./my-button.component.scss'],
})
export class MyButtonComponent implements OnInit {
  constructor() {}
  ngOnInit(): void {}
  acceptData(data: any) {
    console.log(data);
  }
}

如果我将 (inputValue)="acceptData($event) 添加到 my-button.component.html,我什么也得不到,或者如果我将 (inputValue)="acceptData($event) 添加到 login.component.html,我得到错误:

TS2339: Property 'acceptData' does not exist on type 'LoginComponent'.

选项 1:使用 ControlValueAccessor

尽量简单;假设您的应用程序组件中有以下内容

app.component.html

<app-my-input [(ngModel)]='myValue'></app-my-input>
<app-my-button [name]='myValue'></app-my-button>

app.component.ts

 myValue = 'MyValue'

基本上我们绑定到 app.component.ts 中的相同值。所以值会更新到按钮name 属性 改变的时候

现在,如果您尝试 运行 以上操作,您将收到错误消息

No value accessor for control with the name app-my-input

那是因为我们绑定到需要实现ControlValueAccessorngModel。所以我们像下面这样实现这个

我的-input.component.ts

@Component({
  selector: 'app-my-input',
  templateUrl: './my-input.component.html',
  styleUrls: ['./my-input.component.css'],
    providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MyInputComponent),
      multi: true
    },
    ]
})
export class MyInputComponent implements ControlValueAccessor {
  
  myValue = '';
  constructor() { }
  writeValue(value: any): void {
    if (value !== undefined) {
      this.myValue = value;
    }
  }
  onChanges: ($value: any) => void;
  onTouched: () => void;

  registerOnChange(fn: any): void {
    this.onChanges = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }
}

我的-input.component.ts

<input [(ngModel)]='myValue' (ngModelChange)='onChanges(myValue)'>

现在我们的 app-my-input 就像普通输入一样工作,我们可以绑定到 [(ngModel)] 指令

所以现在在我们的 app-my-button 中,我们可以使用 @Input 装饰器

接收它

app-my-button.ts

  @Input() name = "";
  constructor() {}

  ngOnInit(): void {}

  displayReceivedValue() {
    console.log("Received value: ", this.name);
  }

app-my-button.html

<button (click)='displayReceivedValue()'>My button</button>

现在,如果您单击该按钮,您将在控制台中看到一条包含输入值的日志

Demo Here

选项 2:使用 @Output@input 装饰器

要使用 @input@Output,您只需定义您输入的是

export class MyInputComponent implements OnInit {
  
  @Input() input = '';
  @Output() output: EventEmitter<string> = new EventEmitter()
  myValue = '';
  constructor() { }
  onChanges = ($event) => {
    this.output.emit($event)
  }

  ngOnInit() {
    this.myValue = this.input
  }
}

并在 html

<input [(ngModel)]='myValue' (ngModelChange)='onChanges(myValue)'>

现在我们绑定到 (ngModelChange)。当值发生变化时,我们使用定义为 EventEmitter<string>

output 属性 发出值

然后我们可以用

接收这个
<app-my-input [input]='myValue' (output)="myValue = $event"></app-my-input>

See this Demo