简体   繁体   English

Angular 4 在 2 个不相关的组件之间传递数据

[英]Angular 4 pass data between 2 not related components

I have a questions about passing data in Angular.我有一个关于在 Angular 中传递数据的问题。

First, I don't have a structure as <parent><child [data]=parent.data></child></parent>首先,我没有<parent><child [data]=parent.data></child></parent>

My structure is我的结构是

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

So, in <summary /> I have a select that do send value to <child-summary /> and <content /> .因此,在<summary />我有一个选择,可以将值发送到<child-summary /><content />

OnSelect method is well fired with (change) inside <summary /> component. OnSelect 方法在<summary />组件内使用 (change) 很好地触发。

So, I tried with @Input , @Output and @EventEmitter directives, but I don't see how retrieve the event as @Input of the component, unless to go on parent/child pattern.因此,我尝试使用@Input@Output@EventEmitter指令,但我不知道如何将事件检索为组件的 @Input ,除非继续使用父/子模式。 All examples I've founded has a relation between component.我创建的所有示例都具有组件之间的关系。

EDIT : Example with BehaviorSubject not working (all connected service to API works well, only observable is fired at start but not when select has value changed)编辑: BehaviorSubject 不起作用的示例(所有连接到 API 的服务运行良好,仅在启动时触发 observable,但在 select 值更改时不触发)

shared service = company.service.ts (used to retrieve company data) shared service = company.service.ts(用于检索公司数据)

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();
    }
}

invoice.component.ts (the "child") invoice.component.ts(“孩子”)

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 (the trigerring "parent") company.component.ts(触发“父”)

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);
    }
}

This is a case where you want to use a shared service, as your components are structured as siblings and grandchildren.这是您想要使用共享服务的情况,因为您的组件被构造为兄弟姐妹和孙辈。 Here's an example from a video I created a video about sharing data between components that solves this exact problem.这是一个视频示例,我创建了一个关于解决这个确切问题的组件之间共享数据的视频。

Start by creating a BehaviorSubject in the service首先在服务中创建一个 BehaviorSubject

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)
  }

}

Then inject this service into each component and subscribe to the observable.然后将此服务注入每个组件并订阅可观察对象。

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)
  }

}

You can change the value from either component and the value will be updated, even if you don't have the parent/child relationship.您可以从任一组件更改值,即使您没有父/子关系,该值也会更新。

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")
  }

}

There are two solutions for this.对此有两种解决方案。

  1. This can be done through shared service by using observable's.这可以通过使用 observable 的共享服务来完成。

  2. You can use ngrx/store for this.您可以为此使用 ngrx/store。 This is similar to Redux arch.这类似于 Redux arch。 You will be getting data from state.您将从州获取数据。

Here is the simplest example of sharing data between two independent components, using event emitter and service这是在两个独立组件之间共享数据的最简单示例,使用事件发射器和服务

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

Sharing data between two unrelated components: Download or clone the repo from my github account- 在两个不相关的组件之间共享数据:从我的github帐户下载或克隆存储库-

https://github.com/kunalinfo/passing-data-between-two-sibling-unrelated-components https://github.com/kunalinfo/passing-data-between-two-sibling-unrelated-components

When you mention non related components, I'm gonna assume that they don't have any parent component.当您提到非相关组件时,我会假设它们没有任何父组件。 If assumption isn't correct, feel free to read another of my answers where both cases are addressed .如果假设不正确,请随时阅读我的另一个答案,其中解决了两种情况

So, as there's no common parent, we can use an injectable service.因此,由于没有共同的父级,我们可以使用可注入的服务。 In this case, simply inject the service in the components and subscribe to its events.在这种情况下,只需在组件中注入服务并订阅其事件。

(Just like the next image shows - taken from here - except that we'll inject the service in two Components) (就像下图所示 -取自这里- 除了我们将在两个组件中注入服务)

在组件 Angular 中注入服务

The documentation explains it quite well how to Create and register an injectable service .该文档很好地解释了如何创建和注册可注入服务

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM