首页 > 解决方案 > 通过 Observable 传递对象数组

问题描述

我有一个简单的原型表单,它由两个组件(搜索和结果)和一个服务(查询)组成。

在详细介绍之前简要总结一下,我希望在搜索组件上执行一个操作来更新结果窗格中的数据。

在我下面发布的原型中,这适用于一个简单的字符串。我可以在输入框中输入一个字符串,每次单击提交时都会调用设置值的服务(调用 service.setData),结果组件会观察到它相应地更改并更新了标签。我试过对一个对象数组做同样的事情,但无论我尝试什么,它都拒绝实时更新。它会在初始负载上工作。我已将服务添加到提供程序中。

search.component.html - 因为这是一个简单的测试,它有两个按钮调用略有不同的方法。

Set data to:

<input [(ngModel)]="searchTerm" placeholder="Enter data here"/>

<button (click)="getSearchResults1(searchTerm); searchTerm=''">Submit 1</button>
<button (click)="getSearchResults2(searchTerm); searchTerm=''">Submit 2</button>

search.component.ts

  constructor(private queryService: QueryService) {}

  getSearchResults1(searchTerm: string):void {    
    this.queryService.setAccountData1();
    this.queryService.setData(searchTerm);
  }

  getSearchResults2(searchTerm: string):void {
    this.queryService.setAccountData2();
    this.queryService.setData(searchTerm);
  }

  ngOnInit() {  
    this.queryService.setAccountData3();
  }

查询.service.ts

constructor(private http: HttpClient) { }

  private data: BehaviorSubject<string> = new BehaviorSubject(null);

  getData(): Observable<string> {
    return this.data;
  }

  setData(d: string): void {
    this.data.next(d);
  }

  ////////////////////////////////////////////////

  private accountData: Observable<Account[]> = new Observable(null);

  private accountUrl = 'assets/accounts.json';
  private accountUrl2 = 'assets/accounts2.json';
  private accountUrl3 = 'assets/accounts3.json';

  getAccountData(): Observable<Account[]> {
    return this.accountData;
  }

  setAccountData1(): void {
    this.accountData = this.http.get<Account[]>(this.accountUrl)
  }
  setAccountData2(): void {
    this.accountData = this.http.get<Account[]>(this.accountUrl2)
  }
  setAccountData3(): void {
    this.accountData = this.http.get<Account[]>(this.accountUrl3)
  }

results.component.html - 顶部的字符串版本工作正常,尝试使用对象数组执行此操作的两个略有不同的版本都失败了。

The new value is: <br />

<div>{{data|async}}</div>

<br /><hr /><br />

Array is: <br />

<ul class="search-result">
    <li *ngFor="let account of accountData|async" >

        {{account.firstName}}

    </li>
  </ul> 

  <ul class="search-result">
    <li *ngFor="let account2 of accountData2" >

        {{account2.firstName}}

    </li>
  </ul> 

结果.component.ts

  constructor(private queryService: QueryService) {}

  data: Observable<string>;    
  accountData: Observable<Account[]>;    
  accountData2: Account[];

  ngOnInit() {

    this.data = this.queryService.getData();

    this.accountData = this.queryService.getAccountData();

    this.queryService.getAccountData().subscribe(a => this.accountData2 = a);

  }

1) 页面首次加载时,搜索组件的 Onit 会加载 setAccountData3,它会显示第三个帐户数据集中的名字列表。

2)我在搜索组件的输入框中输入一个字符串值,点击任意一个按钮,字符串值会实时输出到结果组件上。

3) 对象数组不会在任一按钮上更新。两个提交按钮都使用稍微不同的更新数组的方法。我可以从输出到控制台得知正在设置数组值,但结果组件看不到这个动作,就像它在字符串版本上使用几乎相同的编码一样。

编辑........ 确认这是一个简单的原型,用于测试我在以后的项目中需要的原则。我知道在这种特殊情况下,我可以简化解决方案以达到我想要的结果。我特别想要一个组件来“监听”服务中的变化并对其采取行动,这很容易适用于字符串,但我无法让它适用于对象数组。

标签: angularrxjsobservable

解决方案


首先,对于 HTML,我不确定您为什么要划分 2 个组件搜索和结果。您可以将两者结合起来。对于 Angular,当您有 2 个 HTML 组件(以您的为例)时,您将有 2 个单独的 component.ts、component.spec.ts 等,并且将它们链接起来会有点挑战。我建议将它们组合在一起。其次,因为您使用的是 [(ngModel)],所以您不必将属性“searchTerm”传递给方法。这是我建议的解决方案

.component.html

    <input [(ngModel)]="searchTerm" placeholder="Enter data here"/>

    <button (click)="getSearchResults1()>Submit 1</button>
    <button (click)="getSearchResults2()>Submit 2</button>



 <-- YOUR RESULT WILL SHOWED HERE -->
   The new value is: <br />

    <div>{{data|async}}</div>

    <br /><hr /><br />

    Array is: <br />

    <ul class="search-result">
        <li *ngFor="let account of searchTerm | async" >

            {{account.firstName}}

        </li>
      </ul> 

      <ul class="search-result">
        <li *ngFor="let account2 of searchTerm " >

            {{account2.firstName}}

        </li>
      </ul> 

从此,您的 component.ts 将是这样的

searchTerm: any;
constructor(private queryService: QueryService) {}

ngOnInit() {  
  this.getSearchResults3();
}

  getSearchResults1()  {    
    this.queryService.setAccountData1()
      .subcribe(data => {
         this.searchTerm = data;
      }
  }

  getSearchResults2()  {
    this.queryService.setAccountData2()
      .subcribe(data => {
         this.searchTerm = data;
      }
  }

  getSearchResults3()  {
    this.queryService.setAccountData3()
        .subcribe(data => {
          this.searchTerm = data;
        }
 }

查询.service.ts

constructor(private http: HttpClient) { }

  private accountUrl = 'assets/accounts.json';
  private accountUrl2 = 'assets/accounts2.json';
  private accountUrl3 = 'assets/accounts3.json';

  setAccountData1(): Observable<Account>{
    return this.http.get<Account>(this.accountUrl)
  }
  setAccountData2(): Observable<Account>{
    return this.http.get<Account>(this.accountUrl2)
  }
  setAccountData3(): Observable<Account>{
    return this.http.get<Account>(this.accountUrl3)
  }

推荐阅读