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

11

我正在开发一个包含搜索功能的应用程序。

目前在应用程序中有两个组件: 1.导航栏 2.搜索网格列表

导航栏组件包含一个文本框,您可以在其中输入搜索查询并按回车键,此组件将进行API调用并获取数据。 当数据返回时,我希望在SearchGridList组件中的数组中填充此数据。

我很难理解在Angular中如何在组件之间传递数据,请有人看看我的代码并指导我。

navbar.component.ts

import { Component, OnInit, Input, Output } from '@angular/core';
import {DataService} from '../../services/data.service';
import {SearchResults} from '../class/search.class';
import {SearchGridListComponent} from '../search-grid-list/search-grid-list.component';
import { EventEmitter } from '@angular/core';

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {

  searchQuery : String;
  //searchResultList : Array<any> = [];

  constructor(private dataService :  DataService) { }

  doSearch () : any
  {
    this.dataService.doSQLSearch(this.searchQuery)
    .then ((data:any)=>{
      for (var i =0; i<data.Results.length;i++){
        let searchObj = new SearchResults(data.Results[i]);
        //I want to push data into array from SearchGrid like this 
        resultGridList.push(searchObj);

      }
    });
   }

  ngOnInit() {
  }
}

导航栏组件.html

<mat-toolbar class="main-header">
  <a href="/">
  <img src="../../../assets/vms-header-logo.png" id= "header-logo">
  </a>
    <form class="search-box">
      <mat-form-field  class="search-box-full-width">
        <input id ="search-textbox" matInput placeholder="Enter a Barcode, DSID or any search term" name="Search" [(ngModel)]="searchQuery" (keyup.enter)="doSearch()" autocomplete="off">
      </mat-form-field>
    </form>
</mat-toolbar>

搜索网格组件.search-grid.component.ts

import { Component, OnInit, Input } from '@angular/core';
import {NavbarComponent} from '../navbar/navbar.component';

@Component({
  selector: 'app-search-grid-list',
  templateUrl: './search-grid-list.component.html',
  styleUrls: ['./search-grid-list.component.css'],
})
export class SearchGridListComponent implements OnInit {
  resultGridList : Array <any> = [];
  constructor() { }

  ngOnInit() {
  }

}

包含网格和导航栏的父组件的 HTML/JS 代码是怎样的? - Kamil Kiełczewski
1
请更具体地说明。您不理解这个链接中的哪些内容? - Randy Casburn
1
请查看此链接:https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service如果组件之间是父子关系,您可以使用输入绑定。 如果它们不是,则最好的解决方案是使用服务,如链接所述。 - Leandro Lima
@KamilKiełczewski - 对的 - 那将是未提及的第三个组件 - 应用程序组件。 - Randy Casburn
4个回答

7

3
好的,我会尽力进行翻译。以下是需要翻译的内容:"yes .. I can recommend BehaviourSubject also. So for example I use this for auth state .. I wrote a post about this: https://medium.com/@fransyozef/my-angular-dashboard-template-part-2-850a0854da74" 是的,我也可以推荐使用BehaviorSubject。例如,我在认证状态中使用它。我写了一篇关于这个的文章:https://medium.com/@fransyozef/my-angular-dashboard-template-part-2-850a0854da74 - fransyozef

6
您需要在导航栏中添加以下@Output事件:
export class NavbarComponent implements OnInit {
   ...
   @Output() public found = new EventEmitter<any>();
   ...
   doSearch () : any
   {
    this.dataService.doSQLSearch(this.searchQuery) .then ((data:any)=>{
      for (var i =0; i<data.Results.length;i++){
        let searchObj = new SearchResults(data.Results[i]);

        this.found.emit(searchObj);  // !!!! here emit event
                                     // however emitting events in loop looks strange... better is to emit one evet

      }
    });
   }
   ...
}

在您的网格组件中,使用@Input作为resultGridList参数。

export class SearchGridListComponent implements OnInit {

  @Input() public resultGridList : Array <any> = [];
  ...
}

好的,现在在您的应用程序组件中以以下方式加入这两个内容:

App 模板 html:

<app-navbar (found)="handleResults($event)"></app-navbar>

<app-search-grid-list [resultGridList]="data"></app-search-grid-list>

在应用的ts文件中:

data = [];
...

handleResults(searchObj) {
  this.data = searchObj
}

3
这帮助我解决了我的问题。只是一个快速的问题,这是否是正确的方法?我知道我可以创建一个服务并注入它,但我不想创建一个只会在应用程序中使用一次的服务。 - curious_debugger
2
通常应用程序有N个服务(取决于restfulapi、db-backend-domain中的资源/请求),这组服务由K个组件使用,其中通常K>N。我不知道你的领域是什么样子的。我的解决方案是标准的方法,然而Hien提出的解决方案也是一个有趣(更先进)的替代方案。 - Kamil Kiełczewski
@KamilKiełczewski 如果我不想在其他组件中的导航栏中进行搜索怎么办?如果我们这样做 <app-navbar (found)="handleResults($event)"></app-navbar>,它需要在每个组件中添加。如果没有添加,它将抛出 NullInjector 错误。在这种情况下,解决方案是什么? - NoobCoder
@NoobCoder 这是一个单独的问题,你可以在stackoverflow上提问。不过我会使用一些带有全局事件的单例服务来解决它。 - Kamil Kiełczewski

0

@Input 用于定义输入属性,以实现组件属性绑定。@Input 装饰器用于从父组件向子组件传递数据(属性绑定)。
组件属性应该使用 @Input 装饰器进行注释,以充当输入属性。


-2
只需将 dataService 注入到 search-grid 组件中。服务是单例的,可以在组件之间共享。
在一个组件中:
dataService.test = "hello";

在另一个组件中:
console.log(dataService.test); // "hello"

这就是服务的作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接