【问题标题】:Pass data from one component to another in angular以角度将数据从一个组件传递到另一个组件
【发布时间】:2019-08-03 04:06:12
【问题描述】:

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

现在我在应用程序中有 2 个组件 1.导航栏 2. 搜索网格列表

Navbar 组件包含一个文本框,您可以在其中输入搜索查询并按 Enter,该组件将进行 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() {
  }
}

navbar.component.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代码如何?
  • 请更具体。 from this具体有什么不明白的?
  • 请查看此链接angular.io/guide/… 如果组件是父子组件,则可以使用输入绑定如果不是,最好的解决方案是使用服务,因为链接正在解释
  • @KamilKiełczewski - 对 - 这将是第三个未提及的组件 - App 组件。

标签: javascript arrays angular typescript components


【解决方案1】:

您可以在DataService 中创建BehaviorSubject

private messageSource = new BehaviorSubject<string>('service');

你可以参考这个演示在组件之间传递数据。

https://stackblitz.com/edit/behavior-subject-2019

【讨论】:

  • 是的 .. 我也可以推荐 BehaviourSubject。因此,例如,我将其用于身份验证状态.. 我写了一篇关于此的帖子:medium.com/@fransyozef/…
【解决方案2】:

您需要在@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>

并且在 App ts 文件中:

data = [];
...

handleResults(searchObj) {
  this.data = searchObj
}

【讨论】:

  • 这帮助我解决了我的问题。只是一个简单的问题,这是正确的方法吗?我知道我可以创建一个服务并注入它,但我不想创建只会在应用程序中使用一次的服务。
  • @KshitijAnilRangari 通常应用程序有 N 个服务(取决于 restfulapi、db-backend-domain 中的资源/请求),并且该组服务由 K 个组件使用,其中通常 K>N。我不知道您的域看起来如何。我的解决方案是标准方法,但是Hien 提出的解决方案也是有趣(并且更先进)的替代方案。
  • @KamilKiełczewski 如果我不想在导航栏中搜索其他组件怎么办?如果我们这样做 &lt;app-navbar (found)="handleResults($event)"&gt;&lt;/app-navbar&gt; ,则需要在每个组件中添加它。如果不是,它将抛出 NullInjector 错误。在这种情况下,解决方案是什么?
  • @NoobCoder 这是一个单独的问题,您可以在 stackoverflow 上提问。但是我会使用一些带有全局事件的单例服务来完成它
【解决方案3】:

@Input用于定义一个输入属性,实现component property binding。 @Inoput 装饰器用于将数据(属性绑定)从父组件传递到子组件。
组件属性应使用 @Input 装饰器进行注释,以充当输入属性。

【讨论】:

    【解决方案4】:

    也只需在search-grid 组件中注入dataService。服务是单例的,您可以跨组件共享它们。

    在一个组件中:

    dataService.test = "hello";
    

    在另一个组件中:

    console.log(dataService.test); // "hello"
    

    这就是服务的用途。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-27
      • 2020-01-09
      • 2017-02-15
      • 1970-01-01
      • 2020-12-25
      相关资源
      最近更新 更多