recargar pasar parametros globales entre comunicacion componentes componente angular angular2-components

pasar - recargar componente angular



Cómo llamar a otra función de componentes en angular2 (6)

Tengo dos componentes como sigue y quiero llamar a una función desde otro componente. Ambos componentes se incluyen en el tercer componente principal mediante la directiva.

Componente 1:

@component( selector:''com1'' ) export class com1{ function1(){...} }

Componente 2:

@component( selector:''com2'' ) export class com2{ function2(){... // i want to call function 1 from com1 here } }

He intentado usar @input y @output pero no entiendo exactamente cómo usarlo y cómo llamar a esa función, ¿alguien puede ayudarme?


Componente 1 (hijo):

@Component( selector:''com1'' ) export class Component1{ function1(){...} }

Componente 2 (padre):

@Component( selector:''com2'', template: `<com1 #component1></com1>` ) export class Component2{ @ViewChild("component1") component1: Component1; function2(){ this.component1.function1(); } }


Depende de la relación entre sus componentes (padre / hijo), pero la mejor forma genérica de hacer que los componentes de comunicación se comuniquen es usar un servicio compartido.

Vea este documento para más detalles:

Dicho esto, puede usar lo siguiente para proporcionar una instancia de com1 en com2:

<div> <com1 #com1>...</com1> <com2 [com1ref]="com1">...</com2> </div>

En com2, puede usar lo siguiente:

@Component({ selector:''com2'' }) export class com2{ @Input() com1ref:com1; function2(){ // i want to call function 1 from com1 here this.com1ref.function1(); } }


Primero, lo que necesita para comprender las relaciones entre los componentes. Entonces puede elegir el método de comunicación correcto. Trataré de explicar todos los métodos que conozco y utilizo en mi práctica para la comunicación entre componentes.

¿Qué tipo de relaciones entre componentes puede haber?

1. Padre> Niño

Compartir datos a través de la entrada

Este es probablemente el método más común para compartir datos. Funciona usando el decorador @Input() para permitir que los datos pasen a través de la plantilla.

parent.component.ts

import { Component } from ''@angular/core''; @Component({ selector: ''parent-component'', template: ` <child-component [childProperty]="parentProperty"></child-component> `, styleUrls: [''./parent.component.css''] }) export class ParentComponent{ parentProperty = "I come from parent" constructor() { } }

child.component.ts

import { Component, Input } from ''@angular/core''; @Component({ selector: ''child-component'', template: ` Hi {{ childProperty }} `, styleUrls: [''./child.component.css''] }) export class ChildComponent { @Input() childProperty: string; constructor() { } }

Este es un método muy simple. Es fácil de usar. También podemos detectar cambios en los datos en el componente secundario utilizando ngOnChanges .

Pero no olvide que si usamos un objeto como datos y cambiamos los parámetros de este objeto, la referencia a él no cambiará. Por lo tanto, si queremos recibir un objeto modificado en un componente hijo, debe ser inmutable.

2. Niño> Padre

Compartir datos a través de ViewChild

ViewChild permite que un componente se inyecte en otro, dando al padre acceso a sus atributos y funciones. Sin embargo, una advertencia es que el child no estará disponible hasta después de que se haya inicializado la vista. Esto significa que necesitamos implementar el enlace del ciclo de vida AfterViewInit para recibir los datos del niño.

parent.component.ts

import { Component, ViewChild, AfterViewInit } from ''@angular/core''; import { ChildComponent } from "../child/child.component"; @Component({ selector: ''parent-component'', template: ` Message: {{ message }} <child-compnent></child-compnent> `, styleUrls: [''./parent.component.css''] }) export class ParentComponent implements AfterViewInit { @ViewChild(ChildComponent) child; constructor() { } message:string; ngAfterViewInit() { this.message = this.child.message } }

child.component.ts

import { Component} from ''@angular/core''; @Component({ selector: ''child-component'', template: ` `, styleUrls: [''./child.component.css''] }) export class ChildComponent { message = ''Hello!''; constructor() { } }

Compartir datos a través de Output () y EventEmitter

Otra forma de compartir datos es emitir datos del elemento secundario, que el padre puede enumerar. Este enfoque es ideal cuando desea compartir los cambios de datos que ocurren en cosas como clics de botones, entradas de formularios y otros eventos de usuario.

parent.component.ts

import { Component } from ''@angular/core''; @Component({ selector: ''parent-component'', template: ` Message: {{message}} <child-component (messageEvent)="receiveMessage($event)"></child-component> `, styleUrls: [''./parent.component.css''] }) export class ParentComponent { constructor() { } message:string; receiveMessage($event) { this.message = $event } }

child.component.ts

import { Component, Output, EventEmitter } from ''@angular/core''; @Component({ selector: ''child-component'', template: ` <button (click)="sendMessage()">Send Message</button> `, styleUrls: [''./child.component.css''] }) export class ChildComponent { message: string = "Hello!" @Output() messageEvent = new EventEmitter<string>(); constructor() { } sendMessage() { this.messageEvent.emit(this.message) } }

3. hermanos

Niño> Padre> Niño

Trato de explicar otras formas de comunicación entre hermanos a continuación. Pero ya podría entender una de las formas de entender los métodos anteriores.

parent.component.ts

import { Component } from ''@angular/core''; @Component({ selector: ''parent-component'', template: ` Message: {{message}} <child-one-component (messageEvent)="receiveMessage($event)"></child1-component> <child-two-component [childMessage]="message"></child2-component> `, styleUrls: [''./parent.component.css''] }) export class ParentComponent { constructor() { } message: string; receiveMessage($event) { this.message = $event } }

child-one.component.ts

import { Component, Output, EventEmitter } from ''@angular/core''; @Component({ selector: ''child-one-component'', template: ` <button (click)="sendMessage()">Send Message</button> `, styleUrls: [''./child-one.component.css''] }) export class ChildOneComponent { message: string = "Hello!" @Output() messageEvent = new EventEmitter<string>(); constructor() { } sendMessage() { this.messageEvent.emit(this.message) } }

child-two.component.ts

import { Component, Input } from ''@angular/core''; @Component({ selector: ''child-two-component'', template: ` {{ message }} `, styleUrls: [''./child-two.component.css''] }) export class ChildTwoComponent { @Input() childMessage: string; constructor() { } }

4. Componentes no relacionados

Todos los métodos que he descrito a continuación se pueden usar para todas las opciones anteriores para la relación entre los componentes. Pero cada uno tiene sus propias ventajas y desventajas.

Compartir datos con un servicio

Al pasar datos entre componentes que carecen de una conexión directa, como hermanos, nietos, etc., debe utilizar un servicio compartido. Cuando tiene datos que siempre deben estar sincronizados, encuentro que RxJS BehaviorSubject es muy útil en esta situación.

data.service.ts

import { Injectable } from ''@angular/core''; import { BehaviorSubject } from ''rxjs''; @Injectable() export class DataService { private messageSource = new BehaviorSubject(''default message''); currentMessage = this.messageSource.asObservable(); constructor() { } changeMessage(message: string) { this.messageSource.next(message) } }

first.component.ts

import { Component, OnInit } from ''@angular/core''; import { DataService } from "../data.service"; @Component({ selector: ''first-componennt'', template: ` {{message}} `, styleUrls: [''./first.component.css''] }) export class FirstComponent implements OnInit { message:string; constructor(private data: DataService) { // The approach in Angular 6 is to declare in constructor this.data.currentMessage.subscribe(message => this.message = message); } ngOnInit() { this.data.currentMessage.subscribe(message => this.message = message) } }

second.component.ts

import { Component, OnInit } from ''@angular/core''; import { DataService } from "../data.service"; @Component({ selector: ''second-component'', template: ` {{message}} <button (click)="newMessage()">New Message</button> `, styleUrls: [''./second.component.css''] }) export class SecondComponent implements OnInit { message:string; constructor(private data: DataService) { } ngOnInit() { this.data.currentMessage.subscribe(message => this.message = message) } newMessage() { this.data.changeMessage("Hello from Second Component") } }

Compartir datos con una ruta

A veces, no solo necesita pasar datos simples entre componentes, sino también guardar algún estado de la página. Por ejemplo, queremos guardar un filtro en el mercado en línea y luego copiar este enlace y enviarlo a un amigo. Y esperamos que abra la página en el mismo estado que nosotros. La primera forma, y ​​probablemente la más rápida, de hacerlo sería utilizar parámetros de consulta .

Los parámetros de consulta se ven más en la línea de /people?id= donde id puede ser igual a cualquier cosa y puede tener tantos parámetros como desee. Los parámetros de consulta estarían separados por el carácter de comercial.

Cuando trabaje con parámetros de consulta, no necesita definirlos en su archivo de rutas, y pueden denominarse parámetros. Por ejemplo, tome el siguiente código:

page1.component.ts

import {Component} from "@angular/core"; import {Router, NavigationExtras} from "@angular/router"; @Component({ selector: "page1", template: ` <button (click)="onTap()">Navigate to page2</button> `, }) export class Page1Component { public constructor(private router: Router) { } public onTap() { let navigationExtras: NavigationExtras = { queryParams: { "firstname": "Nic", "lastname": "Raboy" } }; this.router.navigate(["page2"], navigationExtras); } }

En la página de recepción, recibiría estos parámetros de consulta como los siguientes:

page2.component.ts

import {Component} from "@angular/core"; import {ActivatedRoute} from "@angular/router"; @Component({ selector: "page2", template: ` <span>{{firstname}}</span> <span>{{lastname}}</span> `, }) export class Page2Component { firstname: string; lastname: string; public constructor(private route: ActivatedRoute) { this.route.queryParams.subscribe(params => { this.firstname = params["firstname"]; this.lastname = params["lastname"]; }); } }

NgRx

La última forma, que es más complicada pero más poderosa, es usar NgRx . Esta biblioteca no es para compartir datos; Es una poderosa biblioteca de gestión de estado. En un breve ejemplo, no puedo explicar cómo usarlo, pero puede ir al sitio oficial y leer la documentación al respecto.

Para mí, NgRx Store resuelve múltiples problemas. Por ejemplo, cuando tiene que tratar con observables y cuando la responsabilidad de algunos datos observables se comparte entre diferentes componentes, las acciones de la tienda y el reductor aseguran que las modificaciones de datos siempre se realizarán "de la manera correcta".

También proporciona una solución confiable para el almacenamiento en caché de solicitudes HTTP. Podrá almacenar las solicitudes y sus respuestas para que pueda verificar que la solicitud que está realizando aún no tiene una respuesta almacenada.

Puede leer sobre NgRx y comprender si lo necesita en su aplicación o no:

Finalmente, quiero decir que antes de elegir algunos de los métodos para compartir datos, debe comprender cómo se utilizarán estos datos en el futuro. Quiero decir, tal vez ahora puedes usar solo un decorador @Input para compartir un nombre de usuario y un apellido. Luego agregará un nuevo componente o un nuevo módulo (por ejemplo, un panel de administración) que necesita más información sobre el usuario. Esto significa que puede ser una mejor manera de utilizar un servicio para los datos del usuario o alguna otra forma de compartir datos. Debe pensarlo más antes de comenzar a implementar el intercambio de datos.


Puede acceder al método del componente uno desde el componente dos.

componente uno

ngOnInit() {} public testCall(){ alert("I am here.."); }

componente Dos

import { oneComponent } from ''../one.component''; @Component({ providers:[oneComponent ], selector: ''app-two'', templateUrl: ... } constructor(private comp: oneComponent ) { } public callMe(): void { this.comp.testCall(); }

componente Dos archivos html

<button (click)="callMe()">click</button>


Si com1 y com2 son hermanos, puede usar

@component({ selector:''com1'', }) export class com1{ function1(){...} }

com2 emite un evento usando un EventEmitter

@component({ selector:''com2'', template: `<button (click)="function2()">click</button>` ) export class com2{ @Output() myEvent = new EventEmitter(); function2(){... this.myEvent.emit(null) } }

Aquí el componente principal agrega un enlace de evento para escuchar los eventos myEvent y luego llama a com1.function1() cuando tal evento ocurre. #com1 es una variable de plantilla que permite hacer referencia a este elemento desde otra parte de la plantilla. Usamos esto para hacer que function1() el controlador de eventos para myEvent de com2 :

@component({ selector:''parent'', template: `<com1 #com1></com1><com2 (myEvent)="com1.function1()"></com2>` ) export class com2{ }

Para otras opciones para comunicarse entre componentes, vea también component-interaction


  • Digamos que el primer componente es DbstatsMainComponent
  • 2do componente DbstatsGraphComponent.
  • 1er componente llamando al método del 2do

<button (click)="dbgraph.displayTableGraph()">Graph</button> <dbstats-graph #dbgraph></dbstats-graph>

Tenga en cuenta la variable local #dbgraph en el componente secundario, que el padre puede usar para acceder a sus métodos ( dbgraph.displayTableGraph() ).