use - javascript para angular




Comunicação de Componente Angular 2 Irmãos (8)

Aqui está uma explicação prática simples: simplesmente explicado here

Em call.service.ts

import { Observable } from 'rxjs';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class CallService {
 private subject = new Subject<any>();

 sendClickCall(message: string) {
    this.subject.next({ text: message });
 }

 getClickCall(): Observable<any> {
    return this.subject.asObservable();
 }
}

Componente de onde você deseja chamar observável para informar outro componente em que o botão é clicado

import { CallService } from "../../../services/call.service";

export class MarketplaceComponent implements OnInit, OnDestroy {
  constructor(public Util: CallService) {

  }

  buttonClickedToCallObservable() {
   this.Util.sendClickCall('Sending message to another comp that button is clicked');
  }
}

Componente onde você deseja executar a ação no botão clicado em outro componente

import { Subscription } from 'rxjs/Subscription';
import { CallService } from "../../../services/call.service";


ngOnInit() {

 this.subscription = this.Util.getClickCall().subscribe(message => {

 this.message = message;

 console.log('---button clicked at another component---');

 //call you action which need to execute in this component on button clicked

 });

}

import { Subscription } from 'rxjs/Subscription';
import { CallService } from "../../../services/call.service";


ngOnInit() {

 this.subscription = this.Util.getClickCall().subscribe(message => {

 this.message = message;

 console.log('---button clicked at another component---');

 //call you action which need to execute in this component on button clicked

});

}

Minha compreensão clara sobre a comunicação de componentes, lendo isto: here

Eu tenho um ListComponent. Quando um item é clicado em ListComponent, os detalhes desse item devem ser mostrados em DetailComponent. Ambos estão na tela ao mesmo tempo, então não há roteamento envolvido.

Como eu digo ao DetailComponent em qual item do ListComponent foi clicado?

Eu considerei a emissão de um evento até o pai (AppComponent) e ter o pai definir o selectedItem.id no DetailComponent com um @Input. Ou eu poderia usar um serviço compartilhado com assinaturas observáveis.

EDIT: Definir o item selecionado via event + @Input não aciona o DetailComponent, no entanto, caso eu precise executar código adicional. Então, não tenho certeza se esta é uma solução aceitável.

Mas ambos os métodos parecem muito mais complexos do que o modo Angular 1 de fazer as coisas, seja através de $ rootScope. $ Broadcast ou $ scope. $ Parent. $ Broadcast.

Com tudo no Angular 2 sendo um componente, estou surpreso que não haja mais informações sobre a comunicação de componentes.

Existe outra maneira mais simples de conseguir isso?


Eu tenho passado os métodos setter do pai para um dos seus filhos através de uma ligação, chamando esse método com os dados do componente filho, o que significa que o componente pai é atualizado e, em seguida, pode atualizar seu segundo componente filho com os novos dados. Ele requer ligação 'this' ou usando uma função de seta embora.

Isso tem o benefício de que os filhos não estejam tão ligados uns aos outros, pois não precisam de um serviço compartilhado específico.

Não estou inteiramente certo de que esta é a melhor prática, seria interessante ouvir as opiniões dos outros sobre isso.


No caso de 2 componentes diferentes (não componentes aninhados, pai \ filho \ neto) sugiro-lhe isto:

MissionService:

import { Injectable } from '@angular/core';
import { Subject }    from 'rxjs/Subject';

@Injectable()

export class MissionService {
  // Observable string sources
  private missionAnnouncedSource = new Subject<string>();
  private missionConfirmedSource = new Subject<string>();
  // Observable string streams
  missionAnnounced$ = this.missionAnnouncedSource.asObservable();
  missionConfirmed$ = this.missionConfirmedSource.asObservable();
  // Service message commands
  announceMission(mission: string) {
    this.missionAnnouncedSource.next(mission);
  }
  confirmMission(astronaut: string) {
    this.missionConfirmedSource.next(astronaut);
  }

}

AstronautComponent:

import { Component, Input, OnDestroy } from '@angular/core';
import { MissionService } from './mission.service';
import { Subscription }   from 'rxjs/Subscription';
@Component({
  selector: 'my-astronaut',
  template: `
    <p>
      {{astronaut}}: <strong>{{mission}}</strong>
      <button
        (click)="confirm()"
        [disabled]="!announced || confirmed">
        Confirm
      </button>
    </p>
  `
})
export class AstronautComponent implements OnDestroy {
  @Input() astronaut: string;
  mission = '<no mission announced>';
  confirmed = false;
  announced = false;
  subscription: Subscription;
  constructor(private missionService: MissionService) {
    this.subscription = missionService.missionAnnounced$.subscribe(
      mission => {
        this.mission = mission;
        this.announced = true;
        this.confirmed = false;
    });
  }
  confirm() {
    this.confirmed = true;
    this.missionService.confirmMission(this.astronaut);
  }
  ngOnDestroy() {
    // prevent memory leak when component destroyed
    this.subscription.unsubscribe();
  }
}

Fonte: pai e filhos se comunicam através de um serviço


O serviço compartilhado é uma boa solução para esse problema. Se você quiser armazenar algumas informações de atividade também, poderá adicionar o Serviço Compartilhado à sua lista de provedores de módulos principais (app.module).

@NgModule({
    imports: [
        ...
    ],
    bootstrap: [
        AppComponent
    ],
    declarations: [
        AppComponent,
    ],
    providers: [
        SharedService,
        ...
    ]
});

Então você pode fornecê-lo diretamente aos seus componentes,

constructor(private sharedService: SharedService)

Com o Serviço Compartilhado, você pode usar funções ou criar um Assunto para atualizar vários locais de uma só vez.

@Injectable()
export class FolderTagService {
    public clickedItemInformation: Subject<string> = new Subject(); 
}

Em seu componente de lista, você pode publicar informações de itens clicados,

this.sharedService.clikedItemInformation.next("something");

e então você pode buscar esta informação em seu componente de detalhe:

this.sharedService.clikedItemInformation.subscribe((information) => {
    // do something
});

Obviamente, os dados que listam compartilhamentos de componentes podem ser qualquer coisa. Espero que isto ajude.


Uma maneira de fazer isso é usando um serviço compartilhado .

No entanto eu acho a seguinte solução muito mais simples, permite compartilhar dados entre 2 irmãos (testei isso apenas no Angular 5 )

Em seu modelo de componente pai:

<!-- Assigns "AppSibling1Component" instance to variable "data" -->
<app-sibling1 #data></app-sibling1>
<!-- Passes the variable "data" to AppSibling2Component instance -->
<app-sibling2 [data]="data"></app-sibling2> 

app-sibling2.component.ts

import { AppSibling1Component } from '../app-sibling1/app-sibling1.component';
...

export class AppSibling2Component {
   ...
   @Input() data: AppSibling1Component;
   ...
}

Você precisa configurar o relacionamento pai-filho entre seus componentes. O problema é que você pode simplesmente injetar os componentes filhos no construtor do componente pai e armazená-lo em uma variável local. Em vez disso, você deve declarar os componentes filhos em seu componente pai usando o @ViewChild propriedade @ViewChild . É assim que o seu componente pai deve ser:

import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ListComponent } from './list.component';
import { DetailComponent } from './detail.component';

@Component({
  selector: 'app-component',
  template: '<list-component></list-component><detail-component></detail-component>',
  directives: [ListComponent, DetailComponent]
})
class AppComponent implements AfterViewInit {
  @ViewChild(ListComponent) listComponent:ListComponent;
  @ViewChild(DetailComponent) detailComponent: DetailComponent;

  ngAfterViewInit() {
    // afther this point the children are set, so you can use them
    this.detailComponent.doSomething();
  }
}

https://angular.io/docs/ts/latest/api/core/index/ViewChild-var.html

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

Cuidado, o componente filho não estará disponível no construtor do componente pai, logo após o gancho do ciclo de vida ngAfterViewInit ser chamado. Para capturar este hook simple, implemente a interface AfterViewInit na sua classe pai da mesma forma que faria com OnInit .

Mas, há outros declaradores de propriedade, conforme explicado nesta nota do blog: http://blog.mgechev.com/2016/01/23/angular2-viewchildren-contentchildren-difference-viewproviders/


Atualizado para rc.4: Ao tentar obter dados passados ​​entre componentes secundários em angular 2, A maneira mais simples agora (angular.rc.4) é aproveitar a injeção de dependência hierárquica do angular2 e criar um serviço compartilhado.

Aqui seria o serviço:

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

@Injectable()
export class SharedService {
    dataArray: string[] = [];

    insertData(data: string){
        this.dataArray.unshift(data);
    }
}

Agora, aqui seria o componente PARENT

import {Component} from '@angular/core';
import {SharedService} from './shared.service';
import {ChildComponent} from './child.component';
import {ChildSiblingComponent} from './child-sibling.component';
@Component({
    selector: 'parent-component',
    template: `
        <h1>Parent</h1>
        <div>
            <child-component></child-component>
            <child-sibling-component></child-sibling-component>
        </div>
    `,
    providers: [SharedService],
    directives: [ChildComponent, ChildSiblingComponent]
})
export class parentComponent{

} 

e seus dois filhos

criança 1

import {Component, OnInit} from '@angular/core';
import {SharedService} from './shared.service'

@Component({
    selector: 'child-component',
    template: `
        <h1>I am a child</h1>
        <div>
            <ul *ngFor="#data in data">
                <li>{{data}}</li>
            </ul>
        </div>
    `
})
export class ChildComponent implements OnInit{
    data: string[] = [];
    constructor(
        private _sharedService: SharedService) { }
    ngOnInit():any {
        this.data = this._sharedService.dataArray;
    }
}

criança 2 (é irmão)

import {Component} from 'angular2/core';
import {SharedService} from './shared.service'

@Component({
    selector: 'child-sibling-component',
    template: `
        <h1>I am a child</h1>
        <input type="text" [(ngModel)]="data"/>
        <button (click)="addData()"></button>
    `
})
export class ChildSiblingComponent{
    data: string = 'Testing data';
    constructor(
        private _sharedService: SharedService){}
    addData(){
        this._sharedService.insertData(this.data);
        this.data = '';
    }
}

NOW: Coisas para observar ao usar este método.

  1. Inclua apenas o provedor de serviços para o serviço compartilhado no componente PARENT e NÃO os filhos.
  2. Você ainda tem que incluir construtores e importar o serviço nas crianças
  3. Esta resposta foi originalmente respondida por uma versão beta 2 angular inicial. Tudo o que mudou, no entanto, são as declarações de importação, de modo que é tudo o que você precisa para atualizar se você usou a versão original por acaso.

Isto não é exatamente o que você quer, mas com certeza irá ajudá-lo

Estou surpreso que não haja mais informações por aí sobre a comunicação de componentes <=> considere este tutorial por angualr2

Para comunicação de componentes irmãos, sugiro ir com sharedService . Existem também outras opções disponíveis.

import {Component,bind} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {HTTP_PROVIDERS} from 'angular2/http';
import {NameService} from 'src/nameService';


import {TheContent} from 'src/content';
import {Navbar} from 'src/nav';


@Component({
  selector: 'app',
  directives: [TheContent,Navbar],
  providers: [NameService],
  template: '<navbar></navbar><thecontent></thecontent>'
})


export class App {
  constructor() {
    console.log('App started');
  }
}

bootstrap(App,[]);

Por favor, consulte o link no topo para mais código.

Edit: Esta é uma demonstração muito pequena. Você já mencionou que já tentou com sharedService . Então, por favor, considere este tutorial por angualr2 para mais informações.





typescript