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

Javascript 单击父组件上的按钮时,如何将数据从子组件传递到父组件,javascript,angular,parameter-passing,angular-event-emitter,Javascript,Angular,Parameter Passing,Angular Event Emitter,当用户单击父组件中存在的提交按钮时,我需要将输入值从子组件传递到父组件 childComp模板 <input type="password" [(ngModel)]="userPasswordForm.inputId" class="mr-password-field k-textbox" /> export class PasswordInputComponent{ constructor

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

childComp模板

<input 
  type="password" 
  [(ngModel)]="userPasswordForm.inputId"
  class="mr-password-field k-textbox" 
  />
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>
tempUserFormPasswords:any=[];
.
.
.
getValueFromChild(receivedVal){
    this.tempUserFormPasswords.push(receivedVal);
}
如果该按钮存在于子组件中,则很容易对其进行dio。但是在这种情况下,应该在单击父组件中的按钮时传递值

对于单个子组件: 使用

对于多个子组件使用:

父组件TS文件

<input 
  type="password" 
  [(ngModel)]="userPasswordForm.inputId"
  class="mr-password-field k-textbox" 
  />
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>
tempUserFormPasswords:any=[];
.
.
.
getValueFromChild(receivedVal){
    this.tempUserFormPasswords.push(receivedVal);
}
单子组件:

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);
}
多个子组件:

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);
}
tempUserFormPasswords:any=[];
@ViewChildren(ChildComponent)子级:ChildComponent;
@ViewChildren(ChildComponent)子对象:QueryList;
.
.
.
getValueFromChild(receivedVal){
让数据;
children.forEach(child=>(data=this.updateData(child.data));
这个.tempUserFormPasswords.push(数据);
}

在服务文件中创建行为主体

@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();
    }
}
当一个按钮点击父组件时,我们正在设置数据行为主题,当一个新的值添加到该组件时,它将自动在子组件中订阅。因此,此时我们需要发出一个事件


我想这将有助于您阅读angular!
文档:.
示例:

您可以使用ViewChild完成此操作,正如@Raz Ronen在另一个答案中所说。但请记住,根据角度版本的不同,您可能需要等待执行AfterViewInit生命周期挂钩以与子级交互(或者子级由于未初始化而不可用)

另外,你也可以使用行为主题,比如刚才回答的@Msk Satheesh,这也很好。但是对于这样一个简单的用例来说,这可能被认为有点过分了。 (这是我们通常在组件之间没有关系时所做的,例如一个组件不是另一个组件的子组件)

我的建议是我认为最简单的(同样,他们的答案无论如何都不错); 它与@Msk Satheesh基本相同(但在引擎盖下),只是角度更大一些: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)
  }
}
从'@angular/core'导入{Component};
@组成部分({
选择器:“应用程序父级”,
模板:`
消息:{{Message}}
`,
样式URL:['./parent.component.css']
})
导出类ParentComponent{
构造函数(){}
消息:字符串;
receiveMessage($event){
this.message=$event
}
}
子组件:

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)
  }
}
从'@angular/core'导入{Component,Output,EventEmitter};
@组成部分({
选择器:“应用程序子项”,
模板:`
发送消息
`,
样式URL:['./child.component.css']
})
导出类子组件{
message:string=“来自子组件的字符串”
@Output()messageEvent=neweventemitter();
构造函数(){}
sendMessage(){
this.messageEvent.emit(this.message)
}
}
使用该代码,父组件将始终订阅子组件输出的messageEvent,并且它将在子组件发出后运行该函数(message函数)。使用Angular处理此问题的优点是,我们可以确保我们的应用程序中没有任何内存泄漏(例如缺少取消订阅)。
正在侦听的组件(订阅的父级)时如果被破坏,Angular将自动取消订阅以避免潜在的内存泄漏。

我不明白,请。当您从父级单击
getValueFromChild
时,是否要将值推入
tempUserFormPasswords
数组,但要推入的值来自子组件?谢谢您的回答,但这是错误的这不是我想要的情况,因为我需要在父组件中单击按钮,就像父组件中名为“receiveMessage”的函数一样。单击按钮时,它会从子组件中获取值。我不确定我是否理解“由于我需要在父组件中单击按钮,就像在单击时父组件中名为“receiveMessage”的函数一样,因此它从子组件中获取值“。所以我不确定如何帮助您。我在回答中提到的所有答案都是相同的:它们允许您从子到父共享数据。如果需要相反的(从父到子)您可以简单地使用
input()
而不是
output()
并且没有
事件发射器
。我确实需要将数据从子级传递到父级,但是在您提供的示例中,您在单击时触发的childComp中创建了一个函数。我希望以相同的方式执行此操作,但该按钮存在于父级组件中。您可以使用输入+输出和事件发射器来执行此操作。您可以从m带有
input()的父到子
,然后单击,您可以按照示例进行操作。但是,如果您更喜欢使用
@viewChild
@viewChildren
进行操作,只需这样做即可。这实际上是一样的,只要您的子方法是公共的,就可以从父组件中使用它们,而不会出现任何问题。这似乎只有在我只导入一个子组件时才起作用在父组件中的时间,如果我将其导入两次,则来自其他子输入的其他值将未定义,我可以知道原因吗?如果需要使用两个或更多组件,则必须使用
@ViewChildren
!检查角度文档。同意@GBra关于
@ViewChildren
的意见,是否可以更新您的答案?以及我将更新问题确定,等待问题更新,以便更好地反映解决方案