如何在父组件上单击按钮时将数据从子组件传递到父组件

How to pass data from child component to parent component when button clicked on parent component

当用户单击存在于父组件中的提交按钮时,我需要将输入的值从子组件传递到父组件。

childComp 模板

<input 
  type="password" 
  [(ngModel)]="userPasswordForm.inputId"
  class="mr-password-field k-textbox" 
  />

childComp TS 文件

export class PasswordInputComponent{

    constructor() { }
  
    @Output() inputValue = new EventEmitter<string>();
    userPasswordForm:any={'input':''};

  emitValue(value: string) {
    this.inputValue.emit(value);
  }
}

父组件模板

<child-component (inputValue)="" > </child-component>
<button (click)="getValueFromChild()"> </button>

父组件 TS 文件

tempUserFormPasswords:any=[];
.
.
.
getValueFromChild(receivedVal){
    this.tempUserFormPasswords.push(receivedVal);
}

如果按钮存在于子组件中,则很容易dio它。但是在这种情况下应该在单击父组件中的按钮时传递值!

对于单个 ChildComponent: 使用 ViewChild

对于多个 ChildComponent 使用:ViewChildren

父组件 TS 文件

单个子组件:

tempUserFormPasswords:any=[];
@ViewChild(ChildComponent) child: ChildComponent;
.
.
.
getValueFromChild(receivedVal){
    var data = child.getData();
    this.tempUserFormPasswords.push(data);
}

多个子组件:

tempUserFormPasswords:any=[];
@ViewChildren(ChildComponent) child: ChildComponent;
@ViewChildren(ChildComponent) children: QueryList<ChildComponent>;
.
.
.
getValueFromChild(receivedVal){
    let data;
    children.forEach(child => (data = this.updateData(child.data));
    this.tempUserFormPasswords.push(data);
}

在服务文件中创建一个 BehaviorSubject

@Injectable()
export class dataService {
    data: BehaviorSubject<any> = new BehaviorSubject<any>(null);

    public setData(data: any){
        this.data.next(data);
    }

    public getData(): Observable<any> {
        return this.data.asObservable();
    }
}

您需要订阅子组件中的数据

密码输入组件

export class PasswordInputComponent{

    constructor(private service: dataService) { 
         this.service.getData().subscribe((data) => {
              //Emit the event here
              this.inputValue.emit(value);
         });
    }
  
    @Output() inputValue = new EventEmitter<string>();
    userPasswordForm:any={'input':''};

  emitValue(value: string) {
    this.inputValue.emit(value);
  }
}

ParentComponent.ts

tempUserFormPasswords:any=[];
.
.
.
constructor(private service: dataService) { }
getValueFromChild(receivedVal){
    this.service.setData('');
    this.tempUserFormPasswords.push(receivedVal);
}

当一个按钮点击父组件时我们正在设置数据行为主题,当一个新的值添加到它会自动订阅到子组件component.so,这时我们需要发出一个事件。

我想这会对你有所帮助..

阅读 angular 中的输入和输出装饰器!
文档:sharing-data
示例:examples

您可以使用 ViewChild 来做到这一点,正如@Raz Ronen 在其他答案中所说的那样。但请记住,根据 Angular 版本,您可能需要等待执行 AfterViewInit 生命周期挂钩才能与子项交互(否则子项将不可用,因为它未初始化)。

此外,您可以使用 BehaviorSubject 来完成,就像@Msk Satheesh 刚刚回答的那样,这也非常好。但对于这样一个简单的用例,它可能被认为有点矫枉过正。 (当组件之间没有关系时,我们通常会这样做,例如一个组件不是另一个组件的子组件)

我的建议是我认为最简单的(同样,他们的答案无论如何都不错); 它与@Msk Satheesh 基本相同(但在幕后),只是多了一点 Angular 样式:Output + EventEmitter:

父组件:

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

@Component({
  selector: 'app-parent',
  template: `
    Message: {{message}}
    <app-child (messageEvent)="receiveMessage($event)"></app-child>
  `,
  styleUrls: ['./parent.component.css']
})
export class ParentComponent {

  constructor() { }

  message:string;

  receiveMessage($event) {
    this.message = $event
  }
}

子组件:

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

@Component({
  selector: 'app-child',
  template: `
      <button (click)="sendMessage()">Send Message</button>
  `,
  styleUrls: ['./child.component.css']
})
export class ChildComponent {

  message: string = "a string from child component"

  @Output() messageEvent = new EventEmitter<string>();

  constructor() { }

  sendMessage() {
    this.messageEvent.emit(this.message)
  }
}

通过代码,父组件将始终订阅子组件输出的 messageEvent,并且它将 运行 子组件发出后的函数(消息函数)。使用 Angular 处理这个问题的好处是我们可以确定我们的应用程序中没有任何内存泄漏(例如,缺少取消订阅)。 当正在侦听的组件(订阅的父级)被销毁时,Angular 将自动取消订阅以避免潜在的内存泄漏。