【问题标题】:Angular 4 Master/Detail service communication between children components子组件之间的Angular 4 Master / Detail服务通信
【发布时间】:2017-11-19 15:34:28
【问题描述】:

我在父组件中有 2 个子组件,childA 和 childB 充当 master/detail。

我正在使用从 webAPI 获取数据的共享服务,而这些孩子使用此共享服务来获取数据。

api/messages - 获取所有消息/Master

api/messages/1 - 获取 1 条带有 id/Detail 的消息

作为主人的子 A 使用服务在视图中显示消息列表。 api/messages 返回所有消息,每条消息都有一个id。

现在,当我单击消息上的主列表时,我能够获取消息的 ID 并将其保存到 Master 组件中的变量中。 现在的问题是如何在主组件中单击消息时在详细组件中显示消息详细信息。我尝试将 ID 传递给服务,但它不起作用

消息服务共享:

export class MessageService {

constructor(private http: HttpClient) { }

getMessages(): Observable<any> {
    return this.http.get('/api/messages').map(data => data)

}



getMessageById(): Observable<any> {
    return this.http.get('/api/messages/3' ).map(data => data) 

//id 3 应该来自主组件并传递该 id。

}
}

主组件:显示列表中的消息列表

  emails: any[];

    constructor(private messageService: MessageService) { }


  ngOnInit() {
   this.messageService.getMessages().subscribe(data => this.emails = 
   data.messages);

    }

    }

详细组件

   message;


    constructor(private messageService: MessageService) {
   }


    ngOnInit() {
    this.messageService.getMessageById().subscribe(data => this.message = 
 data);

  }

 }

【问题讨论】:

  • 也只是将 id 传递给子组件是行不通的。它应该将 id 传递给子组件并触发详细组件的功能,可能在子组件中显示详细信息(3)......但是只有在主组件中按下它时才能做到这一点
  • 您可以在子组件中设置 ID 时调用 API,基本上您可以添加一个设置器,您可以在其中检查设置的 ID 并从那里调用 API,将我的答案更新为好吧,干杯!!

标签: angular angular2-services


【解决方案1】:

一个优雅的解决方案是使用主题模式(它是一种可观察的类型)在组件和服务之间进行通信。

主题模式示例:

处理消息的服务:

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

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

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

    clearMessage() {
        this.subject.next();
    }

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

接收消息的应用组件:

import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

import { MessageService } from './_services/index';

@Component({
    moduleId: module.id,
    selector: 'app',
    templateUrl: 'app.component.html'
})

export class AppComponent implements OnDestroy {
    message: any;
    subscription: Subscription;

    constructor(private messageService: MessageService) {
        // subscribe to home component messages
        this.subscription = this.messageService.getMessage().subscribe(message => { this.message = message; });
    }

    ngOnDestroy() {
        // unsubscribe to ensure no memory leaks
        this.subscription.unsubscribe();
    }
}

Subjects Reference

更高级的模式是在您的应用程序中实现Redux。 Redux 的关键思想是这样的:

  • 应用程序的所有数据都在一个称为状态的数据结构中 - 保存在存储中
  • 您的应用从该商店读取状态
  • 这家商店永远不会直接变异
  • 用户交互(和其他代码)触发描述所发生情况的操作
  • 通过将旧状态与称为 reducer 的函数的操作相结合来创建新状态。

您可以在这个详细的Redux Reference with examples 中阅读有关 Redux 的更多信息

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
  • @nyedidikeke 感谢您的建议。我更新了我的答案:)
【解决方案2】:

您可以在您的详细信息组件中拥有一个@Input 属性,并且可以根据您在主组件中选择的内容来更改它。

类似下面的,

 <detail [id]='<id coming from list>'></detail>

在设置 ID 时调用 API,

private _id: string = "";
  @Input()
  get Id(): string {
    return this._id;
  }
  set Id(id: string) {
    if (this._id !== id) {
      this._id = id;

      // call API
    }
  }

现在您可以将主列表中的 id 作为来自主列表组件的事件传递。

【讨论】:

  • 孩子对孩子是什么意思,能举个例子吗?
  • 使用@Input 我们通常可以从父级传递给子级。就我而言,我在父组件中有 2 个子组件。
  • @OleksandrFedorov,组件与组件交互的方式有很多种,可以详细阅读here,干杯!!
  • @OleksandrFedorov,我上面描述的方式被称为调解器模式,其中交互由一个共同的父级完成,所以如果你有一个父组件来调解你可以使用这种技术,话虽如此如果您的组件深入到另一个组件中,就会变得很困难,因此我们使用服务,您可以在服务中传递这些信息,然后您可以从那里传递数据。
猜你喜欢
  • 2019-12-31
  • 2018-10-13
  • 2011-12-23
  • 2020-02-05
  • 1970-01-01
  • 2019-03-24
  • 2018-08-07
  • 2019-01-19
  • 2021-03-02
相关资源
最近更新 更多