T
T
tonx922018-06-09 06:33:16
Angular
tonx92, 2018-06-09 06:33:16

Angular 2+ Why doesn't parent component see EventEmitter .emit()?

Parent component:

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

@Component({
    selector: 'sluhcrm',
    template: `
<h1>{{title}}</h1>
<main-menu (TestEvent)="MenuClick($event)"></main-menu>
`,
    styleUrls: ['app.component.css']
})

export class AppComponent {
    title = 'MyTitle';

    MenuClick(name){
        alert(1);
        console.log(name);
    }
}

Child component:
import { Component, Input, Output, EventEmitter } from '@angular/core';

const menu = [
    {'name':'Главная', 'url':'/', 'active':1},
    {'name':'Районы', 'url':'/', 'active':0},
    {'name':'Точки', 'url':'/', 'active':0},
    {'name':'Посещения', 'url':'/', 'active':0},
    {'name':'Пользователи', 'url':'/', 'active':0}
]

@Component({
    selector: 'main-menu',
    template: `
<div class="menu">
    <div class="punkt" *ngFor="let punkt of menu" [class.active]="punkt.active">
        <a (click)="selectMenu(punkt)">
            {{punkt.name}} {{punkt.active ? '<': ''}}
        </a>
    </div>
</div>
`,
    styleUrls: ['menu.component.css']
})

export class MenuComponent {
    
    @Output('TestEvent') asd = new EventEmitter();

    menu = menu;

    selectMenu(punkt){
        menu.forEach(element => {
            element.active = 0;
        });

        punkt.active = 1;
        this.asd.emit(punkt.name);
    }
    
}

I have already tried everything I could find, for reasons I do not understand, the parent component refuses to catch the TestEvent event, there are no errors, the logs are empty, it stupidly ignores it. selectMenu works fine.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
T
tonx92, 2018-06-09
@tonx92

Thanks, it helped me figure it out.
The reason was the following, in the module the component with the menu was in bootstrap, as soon as it was removed from there, the output worked, can anyone explain to me why this is happening?

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

import { AppComponent } from './main/app.component';
import { MenuComponent } from './main/menu/menu.component';

@NgModule({
  imports: [BrowserModule, FormsModule],
  declarations: [AppComponent, MenuComponent],
  bootstrap: [AppComponent, >>MenuComponent<<]
})

export class AppModule { }

A
Arthur, 2018-06-09
@antoart

Listen, great question.
I forced to go through the documentation and apply deduction)))
As a result, here is a detailed answer for you.
1. Urukhayy gave a partially correct answer. Well, that is, he correctly noted that the entry of the form is preferable to the entry of the form
Angularists themselves no longer recommend using aliases, even tslint in normal projects swears at this and says that the way when alias is specified is not very cool, and it is better not to use this way. It will be difficult to trace these methods in the code, and it will definitely be impossible to “fall through” into the code in the studio.
But you can do it, purely technically :) :)
And in general, in Typescript it is customary to write in camelCase style (testEvent). PascalCase is more like C#.
From the documentation for angular ( https://angular.io/guide/bootstrapping#the-bootstr... it became clear that those components that are written in bootstrap are created when the application starts. Each from scratch with its own structure of child components.
What is it mean for us?
You have created an AppComponent in which a MainComponent has been created with all the necessary connections (@Output). And then the system created a separate MainComponent and placed it where it should be, torn from the parent, such an orphan. Communication lost. That was the point.
And to see it - in MainComponent add

constructor() {
    console.log('main component create');
}

And track how many times the component has been created.
Conclusion:
Question fire! Work on style. Nobody writes punkt. Imagine that the customer is a foreigner. (menuPoint, link, item, point) - item super option))). Read about the style-guide of Angular. It will help to find a common language with other anglers :) :)

U
Urukhayy, 2018-06-09
@Urukhayy

In the child component, replace with this: And in the selectMenu function, call:
this.TestEvent.emit(punkt.name)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question