将数据从一个Angular组件传递到另一个

时间:2017-04-08 15:28:55

标签: javascript angular

是的,这已被问了几次 - 随意合并这个问题 - 但我可能是个懒人。我在页面中有两个组件,如下所示:

<post-list></post-list>
<post-detail><post-detail>

这是一个非常简单的主 - 细节页面。当用户点击post-list中列表中的项目时,post-detail会加载所选帖子并显示它。

问题是如何从post-list获取post-detail的值以使其立即作出反应?我假设post-detail中应该有一个Observable等待更改。我还假设它应该观察输入属性。问题是:我可以从post-list获取值并将其作为输入属性发送到post-detail吗?可以(而且应该)通过父组件路由它,还是应该为此定义服务?

5 个答案:

答案 0 :(得分:2)

一种方法是从@Input和@Output装饰器。您的父组件应该处理传递给子组件和从子组件传递的内容。

<post-list
    (itemSelected)="loadDetails(any)">
</post-list>
<post-detail
    [selectedItem]="any">
<post-detail>

itemSelected - &gt;是一个输出,它是一个EventEmitter,它将从列表组件中选择哪些内容发送到父组件。

loadDetails(any) - &gt;这是你的父组件中的一个方法,它处理列表组件发出的什么,你需要从孩子那里得到什么。

selectedItem - &gt;是一个详细组件中的输入属性,它可以是理想情况下应该从loadDetails结构化的任何类型。

这只是一个简单的模板,可以满足您的要求。 但是也可以编写一个服务来处理这个问题。

答案 1 :(得分:1)

由于两个组件都有一个共同的父组件,因此最简单的方法是使用@Input()和@Output()属性,并让父组件扮演中介者的角色。我录制了一段简短的视频:https://www.youtube.com/watch?v=tSXx4NoKEYY

您还可以使用Router和Observable实现master-detail。在此处发表了博客:https://yakovfain.com/2016/11/20/angular-2-implementing-master-detail-using-router/

答案 2 :(得分:1)

  

问题是我如何从后列表中获取值到后期详细信息以使其立即做出反应?我假设在详细信息中应该有一个Observable等待更改。我还假设它应该观察输入属性。问题是:我可以从post-list获取值并将其作为输入属性发送到post-detail吗?可以(而且应该)通过父组件路由它,还是应该为此定义服务?

这种情况非常简单 - 后列表需要指明何时选择某个项目,并将该“selectedItem”信息传递给后期详细信息以供显示。

如果我处理这种情况,我会使用简单的输入和输出(即属性和事件绑定)来传递组件之间的信息,使用父组件作为通信的中介。您通过父组件路由它 - 具体来说,后列表指示何时选择帖子以及该帖子是什么,而后详细信息只是显示传递给它的任何帖子。

因此,post-list需要一个名为itemSelect的@Output EventEmitter属性或其他适当的属性。此属性的目的是通知任何关心何时选择项目以及该项目是什么的人。

<强> PostListComponent:

export class PostDetailComponent {
   .....
   @Output() postSelect = new EventEmitter();

   // whenever a post is selected, you call this.postSelect.emit(selectedPost)
   // to notify others which post is selected

在PostDetailComponent中:

export class PostDetailComponent {
   .....
   // this is your property binding 
   // used to get data in real time in to the component for display
  @Input() post;

最后,父组件需要一个post属性来接收来自post-list的更新,并将这些更新传递给post-detail。

<强>为父级

ParentComponent只是从PostList中侦听更新,并在接收到它们时,将事件的实质(模板中的$ event值)分配给其内部post属性,然后将其推送到PostDetail。

 @Component({
    .......
    template: `
       <post-list (postSelect)="post = $event"> </post-list>
       <post-detail [post]="post"> </post-detail>
    `
 })
 export class ParentComponent {
     post: any;  // brokers the communication between the two child components
    .......

这就是我的情况。

您可以使用服务来代理通信,但这通常仅在通信方式复杂或视图层次结构中两个组件彼此不相近时才需要,因此很难从一个组件获取信息到另一个。但在你的情况下,服务可能会过度。

See the docs for more info.

答案 3 :(得分:0)

你可以这样说:

1-将 $ rootScope 注入您的两个组件

2-在代码下面将其中一个作为数据接收器实现:

$rootScope.$on('transferDataEvent', function(data) {

  });

3-以及代码下面的另一个电话作为数据发送方

$rootScope.$emit('transferDataEvent', data); // send data

$ on 会成为一名听众   $ emit 通过范围层次结构

向上调度事件

答案 4 :(得分:0)

更容易解决问题的方法是使用模板引用变量:https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ref-vars

我建议,因为你的组件是兄弟姐妹,即。分享同一个父母。

您可以通过以下方式在模板上引用post-list组件:

看看我设置的这个plnkr:https://plnkr.co/edit/C7kjlaZItfn0sE12HNMO?p=preview

这是代码:

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <post-list #postList></post-list>
      <post-detail [text]="postList?.chosen?.detail"></post-detail>
    </div>
  `,
})
export class App {
  name:string;
  constructor() {
    this.name = `Angular! v${VERSION.full}`
  }
}


@Component({
  selector: 'post-detail',
  template: `
    <div>
      <h2>{{text}}</h2>
    </div>
  `,
})
export class PostDetail {
  @Input() text: string;
  constructor() {
  }
}


@Component({
  selector: 'post-list',
  template: `
    <div>
      <ul>
        <li *ngFor="let post of posts; let i = index">
        <button (click)="chosen = posts[i]">{{post.title}}</button>
        </li>
      </ul>
    </div>
  `,
})
export class PostList {
  chosen: any;
  posts: [] =
  [
    { title:"post 1", detail:"post one detail" },
    { title:"post 2", detail:"post two detail" },
    { title:"post 3", detail:"post three detail" },
  ] 
  constructor() {
  }
}