Angular:如何将数据从子组件发送到父组件?

时间:2020-11-02 20:00:52

标签: angular

我正在学习Angular。我已经阅读了documentation和五篇博客文章,内容如泥泞。我认为有两个模板。子模板具有一个按钮。当用户单击按钮时,我希望元素(说明卡)显示在父模板中。当用户再次单击该按钮时,我希望该元素不显示。即,子按钮可打开或关闭父元素。

<button (click)="toggleInstructions()">Instructions</button>

在标头(子)组件中,我创建了一个输出事件发射器sendData,一个布尔变量showInstructions和一个在showInstructions和{之间切换true的函数{1}}。记录false(非常好!)后,它将调用showInstructions发出数据。我创建了一个新变量sendData,因为我对myData的使用感到困惑。

this

在父组件中,我导入了子组件(import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.css'] }) export class HeaderComponent { @Output() sendData = new EventEmitter<boolean>(); showInstructions: boolean = false; toggleInstructions(myData: boolean) { console.log("Clicked!"); switch (true) { case (this.showInstructions === true): this.showInstructions = false; break; case (this.showInstructions === false): this.showInstructions = true; break; default: console.log("Error in switch-case."); } console.log(this.showInstructions); myData = this.showInstructions; console.log(myData); this.sendData.emit(myData); } } ),并创建了一个函数HeaderComponent以接收数据。当我单击按钮时,没有任何记录。

toggledInstructions

我对应该如何工作感到困惑。在documentation中,除了数据变量名称(import { Component } from '@angular/core'; import { HeaderComponent } from './header/header.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { toggledInstructions(myData: boolean) { console.log("Data coming in!"); console.log(myData); } } )之外,没有任何连接发送和接收功能的东西。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

我发现这个ZeroesAndOnes blog post很好地解释了这一点。要解决我的问题,请从博客文章开始并旋转其代码。

child.component.html更改为:

<div style="border: solid 1px gray; padding: 15px; margin-top: 15px;">
    <h2>Child Component</h2>
    <button (click)="clickButton()">Show Element in Parent</button>
</div>

子模板中没有什么特别的。只需一个按钮即可触发控制器中的功能。

child.component.ts更改为:

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
})
export class ChildComponent {
  showElement: boolean = false;
  @Output() buttonClicked: EventEmitter<boolean> = new EventEmitter<boolean>();

  clickButton() {
    console.log("(Child) Value before toggle: " + this.showElement);
    console.log("(Child) Button clicked!");
    switch (true) {
      case (this.showElement === true):
      this.showElement = false;
      break;

      case (this.showElement === false):
      this.showElement = true;
      break;

      default:
      console.log("Error in switch-case.");
    }
    console.log("(Child) Value after toggle: " + this.showElement);
    this.buttonClicked.emit(this.showElement);
  }

}

变量列表以showElement开头,booleanfalse,并且已初始化buttonClicked,即父元素是隐藏的。

接下来是另一个变量,它是Angular魔术的第一位。变量为@Output(),它具有修饰符EventEmitter<boolean>。这个装饰器意味着该变量将在控制器外部可用。变量的类型为@Output() buttonClicked = new EventEmitter<boolean>(); ,并为其分配了新的事件发射器。如果需要较短的行,可以省略该类型:

showElement

下一步是在truefalse之间切换showElement的功能。此功能的底部是Angular魔术的第二位。调用输出事件,并发送app.component.html变量以由事件发射器发射。

现在将父模板<div style="border: solid 1px gray; padding: 15px;"> <app-child (buttonClicked)="parentEventHandlerFunction($event)"> </app-child> <h1>Parent Component</h1> <span><b>Value emitted from child component is:</b></span> {{ valueEmittedFromChildComponent }} <div *ngIf="valueEmittedFromChildComponent"><span style="color: red;"><b>My awesome element!</b></span> </div> </div> 更改为:

  <app-child (buttonClicked)="parentEventHandlerFunction($event)">
  </app-child>

大Angular魔术在父模板中,特别是在此行中:

app-child

指令buttonClicked将子模板嵌入父模板中。 parentEventHandlerFunction是子控制器中的事件发射器。 $event是父控制器中的函数。 app.component.ts是从子级发送到父级的对象。这一行将子控制器和父控制器的各个部分组合在一起,并用等号将它们连接起来。那是最大的Angular魔术。

现在设置父控制器import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', }) export class AppComponent { valueEmittedFromChildComponent: boolean; parentEventHandlerFunction(valueEmitted){ this.valueEmittedFromChildComponent = valueEmitted; console.log("(Parent) Value emitted: " + valueEmitted); } }

valueEmittedFromChildComponent

我们有一个名为boolean的变量,它是parentEventHandlerFunction。然后我们有一个函数valueEmitted和一个参数$eventvalueEmittedFromChildComponent对象来自父模板中的魔术线,并被分配给局部变量valueEmittedFromChildComponent

回到父模板,我们显示局部变量*ngIf并在@Output()中使用它来显示和隐藏元素。

ZeroesAndOne结束了他们的博客文章,“总而言之,angular使得使用@Output()装饰器创建子组件并将其数据发送到其父组件非常容易。”哈哈!这不是我所说的“极其简单”。相比之下,在AngularJS中,两个模板将共享一个控制器。一个模板中的按钮绑定到控制器中的功能,该功能可切换变量,该变量绑定到第二个模板中的元素以显示和隐藏元素。数据从第一个模板到控制器中的单个变量,再到第二个模板。那“非常容易”。

在Angular中,子模板中的按钮会触发子控制器中的功能,与AngularJS相同。但是随后您需要使用事件发射器制作一个 $id = $organization->id; $memberDetails = session()->get('memberDetails'); foreach ($memberDetails as list($type, $name, $number, $email)) { $member = new Member; $member->org_id = $id; $member->type = $type; $member->name = $name; $member->wnumber =$number; $member->email= $email; $member->save(); } 装饰器,并从toggle函数调用该事件发射器。然后将数据发送到父模板中的魔术线,该模板将子控制器和父控制器中的内容组合在一起。然后,数据将转到父控制器,然后返回到父模板以显示或隐藏目标元素。

让我们重复一遍。当用户单击子模板中的按钮时,数据将转到子控制器,在子控制器中,函数将切换该值,然后将数据从该函数发送到事件发射器。事件发射器将数据发送到父模板,后者将数据发送到父控制器,后者将数据发送回父模板以显示或隐藏元素。那不是我所说的容易。

您将如何在React中做到这一点? React更像AngularJS或Angular吗?

答案 1 :(得分:0)

您似乎需要$event变量才能获得发射值:

<button (click)="toggleInstructions($event)">Instructions</button>

toggledInstructions(event: boolean) {
    console.log("Data coming in!", myData);
}

事件绑定(fooevent)允许绑定到DOM事件和EventEmitter事件

更新:

工作代码示例:

ChildComponent.ts:

@Output() public onFooClicked = new EventEmitter<boolean>();

showMenu() {
  this.onFooClicked .emit(true);
}

app.component.ts:

<foo (onFooClicked)="onClicked($event)">
</foo>

onClicked(event: boolean) {
    console.log(`Somebody clicked`, event);
}

In addition, there is a great article how to pass data.