【问题标题】:Angular 9: Parent function not called on EventEmitter.emit from childAngular 9:未从子级调用 EventEmitter.emit 的父函数
【发布时间】:2020-07-18 23:44:19
【问题描述】:

我是一位经验丰富的程序员,但对 Angular 很陌生。

我刚刚学习了一个很好的 Angular 教程,并尝试练习将值从子组件传递给它的调用者(父)。

不知何故,尽管我将复杂性降低到最低限度,但我的父函数甚至没有被调用,我已将其绑定到发射器。

服务应用程序 (ng serve) 后,我在控制台中只看到以下内容:

child.component.ts:17 submitButtonClicked called

我使用 VS Code and Debugger for Chrome 进入了 emit-Call:

submitButtonClicked() {
  console.log("submitButtonClicked called");
  this.emitter.emit("Test");
}

两步后,我登陆了Subject.js,看到它的成员变量“observers”是空的。 我希望观察者数组至少包含 ParentComponent。请参阅页面末尾截取的 Subject.js 代码。

我的意思是,这真的很简单,但我无法确定我的错误在哪里:-/

可能是什么原因和解决方法?

非常感谢您的帮助!

父级 (parent.component.html)

 <p>parent works!</p>
 <app-child (submitButtonClicked)="parentFunction($event)"></app-child>

父级(parent.component.ts)

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

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.scss']
})
export class ParentComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

  parentFunction (str: string) {
    console.log("parentFunction called, str = " + str);
  }
}

子 (child.component.html)

<p>child works!</p>
<button type="submit" (click)="submitButtonClicked()">Submit</button>

子 (child.component.ts)

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.scss']
})
export class ChildComponent implements OnInit {

  @Output() emitter = new EventEmitter<string>();
  constructor() { }

  ngOnInit(): void {
  }

  submitButtonClicked() {
    console.log("submitButtonClicked called");
    this.emitter.emit("Test");
  }

}

根目录 (app.component.html)

&lt;app-parent&gt;&lt;/app-parent&gt;

根目录 (app.component.ts)

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'My App';
}

根模块 (app.module.ts)

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { ParentComponent } from './parent/parent.component';
import { ChildComponent } from './child/child.component';


@NgModule({
  declarations: [
    AppComponent,
    ParentComponent,
    ChildComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Subject.js

export class Subject extends Observable {
    constructor() {
        super();
        this.observers = [];
        this.closed = false;
        this.isStopped = false;
        this.hasError = false;
        this.thrownError = null;
    }
    [rxSubscriberSymbol]() {
        return new SubjectSubscriber(this);
    }
    lift(operator) {
        const subject = new AnonymousSubject(this, this);
        subject.operator = operator;
        return subject;
    }
    next(value) {
        if (this.closed) {
            throw new ObjectUnsubscribedError();
        }
        if (!this.isStopped) {
            const { observers } = this;
            const len = observers.length;
            const copy = observers.slice();
            for (let i = 0; i < len; i++) {
                copy[i].next(value);
            }
        }
    }
 ... // Snippet ends here

我的 Angular 环境(ng --version):

Angular CLI: 9.0.7
Node: 12.16.1
OS: win32 x64
Angular: 9.0.7
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes
Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.7
@angular-devkit/build-angular     0.900.7
@angular-devkit/build-optimizer   0.900.7
@angular-devkit/build-webpack     0.900.7
@angular-devkit/core              9.0.7
@angular-devkit/schematics        9.0.7
@ngtools/webpack                  9.0.7
@schematics/angular               9.0.7
@schematics/update                0.900.7
rxjs                              6.5.5
typescript                        3.7.5
webpack                           4.41.2

【问题讨论】:

    标签: angular


    【解决方案1】:

    您不必深入挖掘。这是一个简单的修复。发射器称为emitter。所以你必须绑定到那个名字。试试下面的

    <app-child (emitter)="parentFunction($event)"></app-child>
    

    或者如果你想绑定到submitButtonClicked,那么发射器应该被称为submitButtonClicked

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

    如果您想了解有关事件发射器的更多信息,可以查看source。它是 Rxjs Subject 的简单扩展。所以当一个事件发射器被创建时,它实际上是一个被@Output()装饰器装饰的名字所调用的observable。因此,要从发射器获取值,需要订阅它。发射器名称是被订阅的 observable 的名称。

    【讨论】:

    • 谢谢,您节省了我接下来的几个小时...我的参考是angular.io/guide/template-syntax#how-to-use-output。但是,即使在那里,我也只是看到,child->parent 映射是通过发射器的名称完成的,而不是调用发射器的子函数的名称。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-14
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    相关资源
    最近更新 更多