【问题标题】:angular 7 observable array filtering error角度 7 可观察数组过滤错误
【发布时间】:2019-04-25 16:56:42
【问题描述】:

我是 Angular 的新手。目前使用 Angular 7 版本。我正在尝试使用 Observable 中的 filter() 方法进行过滤操作。 我创建了一个服务来注入 Httpclient 以从 json 文件中加载数据。 数据正在从 json 加载。现在我正在尝试根据 EventEmitter 过滤数据。

我得到过滤器不是函数错误

country-load.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map, filter, switchMap } from 'rxjs/operators';
import { Observable } from 'rxjs'
import 'rxjs';
import { ArrayType } from '@angular/compiler/src/output/output_ast';
import { of } from 'rxjs/internal/observable/of';

/* interface ServerData {
  shows: Show[];
} */


@Injectable({
  providedIn: 'root'
})
export class CountryLoadService {

  constructor(private http : HttpClient ) {}


  // HTTP get operation to fetch the port data from static JSON
fetchCountry(){
  return this.http.get("assets/data/port_data.json").pipe(map((res) => of(res)));
}
}

header.component.ts

import { Component, OnInit, EventEmitter, Output, Input } from '@angular/core';
import { CountryLoadService } from './../country-load.service';
import { HttpClient } from '@angular/common/http';
import { ArrayType } from '@angular/compiler/src/output/output_ast';
import { Observable } from 'rxjs/internal/Observable';
import { toArray } from 'rxjs/internal/operators/toArray';

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

  //@Input() result:string="";
  @Output() changed = new EventEmitter<string>();

  constructor(private countryLoadService : CountryLoadService) {}

  countryData;

  ngOnInit() {
  this.countryLoadService.fetchCountry().subscribe(data => {
    console.log(data);
    console.log(this.countryData);
    this.countryData = data;
    console.log(this.countryData);
  })

  }

  onChange(countryName:string){
    this.changed.emit(countryName);
  }
}

header.component.html

<table width="100%" border="0" cellpadding="0" cellspacing="0"
      height="8">
      <tr>
        <td width="70%" align="left" valign="middle" class="toplinks">
          <app-menutab></app-menutab>
        </td>

        <td width="5%" align="right" valign="middle" class="toplinks">
          <label class="toplinks">Load Country</label>
        </td>
        <td width="10%" align="right" valign="middle" class="toplinks">
          <select #input1 style="width: 135px; font-family: Arial narrow; font-size: 8pt"
          name="countryCode" (change)="onChange(input1.value)">
          <option *ngFor="let cn of (countryData | async)">{{cn.country_name}}</option>
          <!-- <input [(ngModel)]="countryData[index]" placeholder="item"> -->
        </select>
        </td>
      </tr>
    </table>

create-tariff.component.ts

import { Component, OnInit } from '@angular/core';
import { CountryLoadService } from './../country-load.service';
import { Observable, Subject, asapScheduler, pipe, of, from,
  interval, merge, fromEvent } from 'rxjs';
import { ArrayType } from '@angular/compiler/src/output/output_ast';
import { map, startWith, filter } from 'rxjs/operators';
import 'rxjs';
import { Country } from './Country'
import { concat } from 'rxjs/internal/observable/concat';

@Component({
  selector: 'app-create-tariff',
  templateUrl: './create-tariff.component.html',
  styleUrls: ['./create-tariff.component.css']
})


export class CreateTariffComponent implements OnInit {

  //jsonData : Observable<any>[] = [];
  //jsonData : Country[] = [];
  jsonData;

  constructor(private currencyLoadService : CountryLoadService) {}

  ngOnInit() {
    this.currencyLoadService.fetchCountry().subscribe(data => {
      console.log(typeof(data));
      this.jsonData = data;
      //this.jsonData = Object.entries(data).map(([type, value]) => ({type, value}));
      console.log(this.jsonData);
    })

    }
  onChanged(value:string){
    if(value!='')
    {
      console.log('foo1111');
      console.log(this.jsonData);
      this.jsonData = this.jsonData.filter(res =>res.country_name.startsWith(value));
      //this.jsonData = this.jsonData.map(resp => resp.filter(res => res.country_name.startsWith(value)));
      //const source = from(this.jsonData);
      //const ex = source.pipe(filter(res => res.country_name.starstWith(value)));
      }
      else{
        this.currencyLoadService.fetchCountry().subscribe(
            (data => {
              this.jsonData = data;})
          );
      }
  }

}

create-tariff.component.html

<app-header (changed)="onChanged($event)"></app-header>
        <span *ngFor="let item of (jsonData | async)">{{item.currency}}</span>

port_data.json

[
    {
        "country_name": "Germany",
        "load_port": [
            "DEBRV06",
            "DEBRVTM",
            "DEHAMCA",
            "DEHAMEK"
        ],
        "currency": "EUR"
    },
    {
        "country_name": "Denmark",
        "load_port": [
            "DKAARPT",
            "DKCPHTM"
        ],
        "currency": "DKK"
    },
    {
        "country_name": "China",
        "load_port": [
            "CNIWNCT",
            "CNIWNMC",
            "CNNANCT",
            "CNNPOYD"
        ],
        "currency": "CNY"
    }
]

当尝试根据从 EventEmitter 收到的值进行过滤时,我收到以下错误。

我尝试了从互联网上收集的不同选项,但到目前为止还没有运气。

任何帮助将不胜感激。

ERROR TypeError: this.jsonData.filter is not a function
    at CreateTariffComponent.push../src/app/create-tariff/create-tariff.component.ts.CreateTariffComponent.onChanged (create-tariff.component.ts:40)
    at Object.eval [as handleEvent] (CreateTariffComponent.html:3)
    at handleEvent (core.js:19628)
    at callWithDebugContext (core.js:20722)
    at Object.debugHandleEvent [as handleEvent] (core.js:20425)
    at dispatchEvent (core.js:17077)
    at core.js:18567
    at SafeSubscriber.schedulerFn [as _next] (core.js:10250)
    at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:196)
    at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next (Subscriber.js:134)

编辑 1 请查看控制台日志我得到的这个 json 数据

Observable {_isScalar: true, _subscribe: ƒ, value: Array(3)}
value: Array(3)
0: {country_name: "Germany", load_port: Array(4), currency: "EUR"}
1: {country_name: "Denmark", load_port: Array(2), currency: "DKK"}
2: {country_name: "China", load_port: Array(4), currency: "CNY"}
length: 3
__proto__: Array(0)
_isScalar: true
_subscribe: ƒ (subscriber)
__proto__: Object

编辑 2 这就是我在执行 toPromise() 时在控制台中得到的内容

ZoneAwarePromise {__zone_symbol__state: null, __zone_symbol__value: Array(0)}
__zone_symbol__state: true
__zone_symbol__value: Array(3)
0: {country_name: "Germany", load_port: Array(4), currency: "EUR"}
1: {country_name: "Denmark", load_port: Array(2), currency: "DKK"}
2: {country_name: "China", load_port: Array(4), currency: "CNY"}
length: 3
__proto__: Array(0)
__proto__: Object

【问题讨论】:

  • 需要在 stackblitz 中看到这一点。您从 AJAX 服务返回的数据似乎返回了一个流数组,而不是您可以调用 map 的流本身。但这是在调试器中没有看到的猜测。
  • 你确定你从 http.get 得到响应?您的 http 在管道后缺少 .subscribe。
  • 初始化 jsonData = [] 。由于第一次角度运行 ngOnChange 时未定义。
  • 试过 jsonData = [];获取 [ts] 属性 'filter' 在类型 '{}' 上不存在错误>> this.jsonData = this.jsonData.filter(res =>res.country_name.startsWith(value));

标签: javascript angular observable angular7


【解决方案1】:

this 很可能在 onChanged 中不正确。它以某种方式编译得很好,但在运行时它可能不是你所期望的,可能类似于MapSubscriber

【讨论】:

    【解决方案2】:

    data = [ { "country_name": "Germany", "load_port": [ "DEBRV06", "DEBRVTM", "DEHAMCA", "DEHAMEK" ], "currency": "EUR" }, { "country_name": "Denmark", "load_port": [ "DKAARPT", "DKCPHTM" ], "currency": "DKK" }, { "country_name": "China", "load_port": [ "CNIWNCT", "CNIWNMC", "CNNANCT", "CNNPOYD" ], "currency": "CNY" } ];
    
    
    value = "Germany";
    
    var jsonData = data.filter(res =>res.country_name.startsWith(value));
    
    console.log(jsonData)

    对我来说看起来不错。 尝试了解您发送的数据是否实际上是对象数组而不是字符串或其他东西。

    好吧,就像我想的那样,您的 get 请求不正确。

    fetchCountry(){
      return this.http.get("assets/data/port_data.json").toPromise().then(d=>d);
    }
    

    当你收到标题组件时:

    this.countryData = this.countryLoadService.fetchCountry();
    

    【讨论】:

    • 我已经更新了上面的问题并分享了 Observable 数组的控制台日志
    • 根据您的评论,我尝试使用 toPromise()。但低于错误。类型错误:this.currencyLoadService.fetchCountry(...).subscribe
    • 你改变了你接收数据的方式?因为它不再是可观察的,所以它变成了一个承诺。
    • 你能举个例子吗,因为我对此很陌生
    • 我试过这个。然后我在 *ngfor 中收到以下错误。 ERROR 错误:找不到类型为“object”的不同支持对象“[object Promise]”。 NgFor 只支持绑定到 Arrays 等 Iterables。
    猜你喜欢
    • 2019-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-05
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    • 2018-11-23
    相关资源
    最近更新 更多