web-dev-qa-db-ger.com

Angular 4-Pass-Daten zwischen 2 nicht verwandten Komponenten

Ich habe eine Frage zur Weitergabe von Daten in Angular.

Erstens habe ich keine Struktur als <parent><child [data]=parent.data></child></parent>

Meine Struktur ist 

<container>
  <navbar>
    <summary></summary>
    <child-summary><child-summary>
  </navbar>
  <content></content>
</container>

Also habe ich in <summary /> eine Auswahl, die Wert an <child-summary /> und <content /> sendet.

Die OnSelect-Methode wird gut mit (change) in der <summary />-Komponente ausgelöst.

Also habe ich es mit den Anweisungen @Input, @Output und @EventEmitter versucht, aber ich sehe nicht, wie das Ereignis als @Input der Komponente abgerufen wird, es sei denn, es wird ein Eltern/Kind-Muster verwendet. Alle Beispiele, die ich gegründet habe, haben eine Beziehung zwischen den Komponenten.

BEARBEITEN: Beispiel, bei dem BehaviorSubject nicht funktioniert (alle mit der API verbundenen Dienste funktionieren gut, nur Observable wird beim Start ausgelöst, jedoch nicht, wenn sich bei select der Wert geändert hat)

shared Service = company.service.ts (wird zum Abrufen von Firmendaten verwendet)

import { Injectable } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/toPromise';

@Injectable()
export class SrvCompany {

    private accountsNumber = new BehaviorSubject<string[]>([]);
    currentAccountsNumber = this.accountsNumber.asObservable();

    changeMessage(accountsNumber: string[]) {
        this.accountsNumber.next(accountsNumber);
    }

    private _companyUrl = 'api/tiers/';

    constructor(private http: Http) { }

    getSociete(): Promise<Response> {
        let url = this._companyUrl;
        return this.http.get(url).toPromise();
    }
}

bill.component.ts (das "Kind")

import { Component, OnInit, Input } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';

import { SrvInvoice } from './invoice.service';
import { SrvCompany } from '../company/company.service';

@Component({
    selector: 'invoice',
    templateUrl: 'tsScripts/invoice/invoice.html',
    providers: [SrvInvoice, SrvCompany]
})

export class InvoiceComponent implements OnInit  {

    invoice: any;

    constructor(private srvInvoice: SrvInvoice, private srvCompany: SrvCompany)
    {

    }

    ngOnInit(): void {
        //this.getInvoice("F001");

        // Invoice data is linked to accounts number from company.
        this.srvCompany.currentAccountsNumber.subscribe(accountsNumber => {
            console.log(accountsNumber);
            if (accountsNumber.length > 0) {
                this.srvInvoice.getInvoice(accountsNumber).then(data => this.invoice = data.json());
            }
        });
    }

    //getInvoice(id: any) {
    //    this.srvInvoice.getInvoice(id).then(data => this.invoice = data.json());
    //}
}

company.component.ts (der trigerring "Eltern") 

import { Component, Inject, OnInit, Input } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';

import { SrvCompany } from './company.service';

@Component({
    selector: 'company',
    templateUrl: 'tsScripts/company/company.html',
    providers: [SrvCompany]    
})

export class CompanyComponent implements OnInit {

    societes: any[];    
    soc: Response[]; // debug purpose
    selectedSociete: any;

    ville: any;
    ref: any;
    cp: any;
    accountNumber: any[];

    constructor(private srvSociete: SrvCompany)
    {

    }

    ngOnInit(): void {
        this.getSocietes();
    }

    getSocietes(): void {

        this.srvSociete.getSociete()
            .then(data => this.societes = data.json())
            .then(data => this.selectItem(this.societes[0].Id));
    }

    selectItem(value: any) {
        this.selectedSociete = this.societes.filter((item: any) => item.Id === value)[0];
        this.cp = this.selectedSociete.CodePostal;
        this.ville = this.selectedSociete.Ville;
        this.ref = this.selectedSociete.Id;
        this.accountNumber = this.selectedSociete.Accounts;
        console.log(this.accountNumber);
        this.srvSociete.changeMessage(this.accountNumber);
    }
}
22
User.Anonymous

In diesem Fall möchten Sie einen gemeinsam genutzten Dienst verwenden, da Ihre Komponenten als Geschwister und Enkel strukturiert sind. Hier ist ein Beispiel aus einem Video. Ich habe ein Video über das Teilen von Daten zwischen Komponenten erstellt, das genau dieses Problem löst. 

Beginnen Sie mit dem Erstellen eines BehaviorSubject im Dienst

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class DataService {

  private messageSource = new BehaviorSubject("default message");
  currentMessage = this.messageSource.asObservable();

  constructor() { }

  changeMessage(message: string) {
    this.messageSource.next(message)
  }

}

Fügen Sie diesen Dienst dann in jede Komponente ein und abonnieren Sie das Beobachtbare. 

import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
  selector: 'app-parent',
  template: `
    {{message}}
  `,
  styleUrls: ['./sibling.component.css']
})
export class ParentComponent implements OnInit {

  message:string;

  constructor(private data: DataService) { }

  ngOnInit() {
    this.data.currentMessage.subscribe(message => this.message = message)
  }

}

Sie können den Wert einer der beiden Komponenten ändern und der Wert wird aktualisiert, auch wenn Sie keine Eltern-Kind-Beziehung haben. 

import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
  selector: 'app-sibling',
  template: `
    {{message}}
    <button (click)="newMessage()">New Message</button>
  `,
  styleUrls: ['./sibling.component.css']
})
export class SiblingComponent implements OnInit {

  message:string;

  constructor(private data: DataService) { }

  ngOnInit() {
    this.data.currentMessage.subscribe(message => this.message = message)
  }

  newMessage() {
    this.data.changeMessage("Hello from Sibling")
  }

}
61
JeffD23

wenn die Komponente nicht verwandt ist, müssen Sie den Service verwenden 

https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

0
CharanRoot

Dafür gibt es zwei Lösungen.

  1. Dies kann durch einen gemeinsamen Dienst unter Verwendung von Observable erfolgen.

  2. Sie können dazu ngrx/store verwenden. Dies ist ähnlich zu Redux Arch. Sie erhalten Daten vom Status.

0
Praneeth Reddy

Hier ist das einfachste Beispiel für die gemeinsame Nutzung von Daten zwischen zwei unabhängigen Komponenten mithilfe von Event Emitter und Service

https://stackoverflow.com/a/44858648/830062

0
Rohit Parte