Búsqueda de sitios web

typescript - Angular 2 llamar a un método en un componente anidado


He encontrado algunas respuestas antiguas sobre esto, pero los métodos que utilizan ya no son válidos. Tengo un componente de encabezado

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx'; 

import { AuthenticationService } from '../_services/Authentication.Service';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
  loading = false;
  error = '';
  isLoggedIn = false;
  showMessageWindow = false;
  messageType: string = "";
  messageText: string = "";
  public currentUser: any = null;

  constructor(private _auth: AuthenticationService, private router: Router) { }

  ngOnInit() {
    if(this._auth.isLoggedIn()) {
      this.isLoggedIn = true;
    }
    else {
      this._auth.logout();
      this.isLoggedIn = false;
      this.router.navigate(['/']);
    }
  }

  showMessage(message: string, type: string) {
    this.messageText = message;
    this.messageType = type;
    this.showMessageWindow = true;
  }
}

Es bastante básico, muestra y gestiona qué navegación se puede ver dependiendo de si alguien ha iniciado sesión y quién es. Tengo una advertencia/alerta incorporada en el componente de encabezado. No todas las páginas usan el encabezado, así que lo estoy importando en los componentes que sí lo usan y colocándolo en la plantilla del componente poniendo <app-header></app-header> en la parte superior.

Here is a component that uses the header.
import { Component, OnInit } from '@angular/core';
import { HeaderComponent } from '../header/Header.Component';
import { Router, ActivatedRoute } from '@angular/router';

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

  constructor( private router: Router, private activatedRoute: ActivatedRoute) { }

  ngOnInit() {

  }

}

Quiero poder poner un método en este componente que haga una llamada a showMessage() desde el componente de encabezado. He intentado varias formas con éxito mínimo. Mi mayor pregunta es cómo puedo referenciar el componente incrustado. Revisé la documentación, pero siempre usan una plantilla directamente en el componente y no usan un archivo HTML separado.

Si intento agregar

  @ViewChild(HeaderComponent)
  private header: HeaderComponent;

en mi CensusComponent recibo una advertencia:

WARNING in ./src/app/header/Header.Component.ts
There are multiple modules with names that only differ in casing.
This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
Use equal casing. Compare these module identifiers:

Respuesta #1

Usa la factoría del decorador ViewChild

// Here is a component that uses the header.

import {ViewChild} from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {HeaderComponent} from '../header/Header.Component';
import {Router, ActivatedRoute} from '@angular/router';

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

  // The argument `HeaderComponent` tells the framework to bind to the child 
  // component whose constructor function is `HeaderComponent`
  @ViewChild(HeaderComponent) header: HeaderComponent;

  constructor(readonly router: Router, readonly activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    this.header.showMessage('an error occurred!', 'error');
  }
}

El error que recibes:

WARNING in ./src/app/header/Header.Component.ts
There are multiple modules with names that only differ in casing.
This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
Use equal casing. Compare these module identifiers:

es completamente ortogonal.

Específicamente, significa que cuando importaste header/Header.component para registrarlo en tu NgModule, importaste el componente usando un especificador de módulo con mayúsculas y minúsculas diferentes. Por ejemplo, header/header.component

Este es un problema que puedes y debes solucionar. Solo asegúrate de que todas las importaciones usen la misma mayúscula y minúscula.

Recomiendo usar nombres de archivo en minúsculas y especificadores de módulo en minúsculas en todas partes. Una simple búsqueda y reemplazo debería encargarse de ello.

Respuesta #2

¿Has pensado en intentar usar ViewChild? Eso debería permitirte obtener una referencia al componente de encabezado y llamar al método showMessage().

https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-view-child

Artículos relacionados