bugfix> angular > 投稿

サブスクライブするオブジェクトの処理方法がわかりません。オブジェクトは次の構造です。

{
  data:{
       date: "2018-02-20 13:10:23",
       text: "Описание",
       id: 1,
       items: [
              0: {
                 date: "2018-02-20 13:10:23",
                 text: "Описание",
                 images: [
                         0: "image1.jpg",
                         1: "image2.jpg"
                         ],
                 name: "Изображения",
                 type: "images"
                 },
              1: {
                 date: "2018-02-20 13:10:23",
                 text: "Описание",
                 image: null,
                 type: "video",
                 url: "https://www.youtube.com/embed/v64KOxKVLVg"
                 }
              ]
       }
}

私はサービスを通してアピー​​ルします:

import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';
@Injectable()
export class VideoService {
    constructor(private http: HttpClient) {}
    getVideoTape() {
        return this.http.get(`http://ip_adress/api/v1/mixed_galleries/1`);
    }
}

インターフェイスモデルがあります。

export class VideoListModel {
    constructor(
        public created_at: string,
        public description: string,
        public id: number,
        public items: any[],
        public name: string
    ) {}
}

そして、コンポーネントで処理を行います:

import {Component, OnDestroy, OnInit} from '@angular/core';
import {Observable, Subscription} from 'rxjs';
import {filter} from 'rxjs/operators';
import {VideoService} from '../shared/services/video.service';
import {VideoListModel} from '../../shared/models/video-list.model';
@Component({
  selector: 'app-video-index',
  templateUrl: './video-index.component.html',
  styleUrls: ['./video-index.component.scss']
})
export class VideoIndexComponent implements OnInit, OnDestroy {
    private videoTape = [];
    private _subscription2: Subscription;
    constructor( private videoService: VideoService ) { }
  ngOnInit() {
      this._subscription2 = this.videoService.getVideoTape()
          .subscribe((data: VideoListModel[]) => {
          this.videoTape = data;
          console.log(this.videoTape);
      });
  }
    ngOnDestroy() {
        this._subscription2.unsubscribe();
    }
}

タスクは、タイプ「ビデオ」によってオブジェクトから選択を行うことです。 AJAX + jQueryを介して問題なく実行でき、Angularでは比較的新しいです。昨日たくさんのビデオレッスンをシャベルしましたが、そのような複雑なオブジェクトをフィルタリングする例はどこにもありません。

建設:

this._subscription2 = this.videoService.getVideoTape()
          .pipe(filter((data: VideoListModel[]) => data.items.type === 'video'))
          .subscribe((data: any) => {
              this.videoTape = data.data;
              console.log(this.videoTape);
          });

動作しません。結果は、「プロパティ 'items'はタイプ 'VideoListModel []'に存在しません」というエラーです。直感的には、問題はインターフェイスにある可能性が高いことを理解していますが、インターフェイスを変更してフィルタリングが正しく機能するようにする方法を理解することはできません。複雑なオブジェクトのフィルタリングに遭遇した場合は、この問題を解決する方法を教えてください。

回答 4 件
  • VideoModelsの配列はありませんが、 items の配列があります  オブジェクト内。コンテンツ全体をフィルターにパイプすると、配列からアイテムをフィルターできますが、オブジェクトがあります。次の回避策を試すことができます。

    このようなインターフェースを作成する

    interface Item {
      date: Date;
      text: string;
      images: string[];
      name: string;
      type: string;
    }
    export interface VideoModel {
      data: {
        date: Date;
        text: string;
        id: number;
        items: Item[];
      }
    }
    
    

    その後、次のようにサービスでHttpClientを使用できます

    import { Observable } from 'rxjs';
    import { map, catchError } from 'rxjs/operators';
    [...]
    getVideoTape(): Observable<VideoModel> {
      return this.http.get<VideoModel>(url).pipe(
        map(model => {
          const items = model.data.items.filter(item => item.type === 'video');
          model.data.items = items;
          return model;
        }),
        catchError(error => console.error(error))
      );
    }
    
    

    有効なjson、string []ではないため、画像配列に注意してください。トラフィックを減らすために、サーバー側のタイプをフィルタリングする方が良いと思いませんか?

  • JSONデータが無効です。

    そのはず

    {
    "data":{
         "date": "2018-02-20 13:10:23",
         "text": "tt",
         "id": 1,
         "items": [
                {
                   "date": "2018-02-20 13:10:23",
                   "text": "Описание",
                   "images": [
                           "image1.jpg",
                           "image2.jpg"
                           ],
                   "name": "Изображения",
                   "type": "images"
                   },
                {
                   "date": "2018-02-20 13:10:23",
                   "text": "Описание",
                   "image": null,
                   "type": "video",
                   "url": "https://www.youtube.com/embed/v64KOxKVLVg"
                   }
                ]
         }
    }
    
    

    その後、http://json2ts.com/

    あなたのモデルは

    export interface Item {
        date: string;
        text: string;
        images: string[];
        name: string;
        type: string;
        image?: any;
        url: string;
    }
    export interface Data {
        date: string;
        text: string;
        id: number;
        items: Item[];
    }
    export interface VideotapeAnswer {
        data: Data;
    }
    
    

  • あなたはその data と言う  は array です  タイプ VideoListModel の 、原因の配列にプロパティ items がありません 。あなたがしたことは Array.items.type のようなものです  意味がありません。おそらくもっと洗練されたソリューションがありますが、結果配列をフィルターを使用できる観測可能なものにマッピングしてみてください。

    this._subscription2 = this.videoService.getVideoTape()
    .pipe(
        map(data => from(data).pipe(filter((d: VideoListModel) => d.items.type === 'video')))
        tap(data => data.subscribe(d => {
            this.videoTape.push(d);
        }))
    ).subscribe();
    
    

    さらに、角度バージョン4+を使用する場合は、このようにデータをマッピングします

    getVideoTape() {
        return this.http.get<VideoListModel[]>(`http://ip_adress/api/v1/mixed_galleries/1`);
    }
    
    

  • @Pieroによって提案された変更を含めると、サービスは観測可能なものを返しません。

    import {HttpClient} from '@angular/common/http';
    import {Injectable} from '@angular/core';
    @Injectable()
    export class VideoService {
        constructor(private http: HttpClient) {}
        getVideoTape():Observable<any>  {
            return this.http.get(`http://ip_adress/api/v1/mixed_galleries/1`);
        }
    }
    
    

あなたの答え