Построение родительского дочернего объекта внутри метода подписки - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть Angular-компонент, который подписывается на наблюдаемое, возвращаемое Angular Service.

Компонент: help.component.ts

import { WikiService } from '../../../services/wiki.service';

import { WikiTree } from '../../../interfaces/WikiTree';

export class HelpComponent implements OnInit {

    wikiTree$: Observable<WikiTree>
    wikiChildTree$: Observable<WikiTree>

    public infoCards: Array<Object>;

    constructor(private wikiService: WikiService) {}

    ngOnInit() {
            this.wikiTree$ = this.wikiService.GetWikiHierarchy();
            this.wikiTree$.subscribe((data)=>{
            const newInfoCards = data.page.results.map(result => (
            {
              "image": "",
              "title": result.title,
              "titleLink": "/page/wiki/"+ result.id,
              "children": []  /*TODO: Populate this array with a Service call based on result.id*/
            }))
            this.infoCards = [...this.infoCards,...newInfoCards]
          },
          (err) => {
            console.log(err);
          }
       );
    }

Наблюдаемая wikiTree$ имеет следующий JSON, преобразованный в TypeScript:

{
    "page": {
        "results": [
            {
                "id": "123456789",
                "type": "page",
                "status": "current",
                "title": "Start here",
                "extensions": {
                    "position": 0
                },
                "_links": {
                    "webui": "/display/MYSPACE/Start+here",
                    "edit": "/pages/resumedraft.action?draftId=123456789",
                    "tinyui": "/x/BQD2Mw",
                    "self": "https://wiki.abc.com/rest/api/content/123456789"
                },
                "_expandable": {
                    "container": "/rest/api/space/MYSPACE",
                    "metadata": "",
                    "operations": "",
                    "children": "/rest/api/content/123456789/child",
                    "restrictions": "/rest/api/content/123456789/restriction/byOperation",
                    "history": "/rest/api/content/123456789/history",
                    "ancestors": "",
                    "body": "",
                    "version": "",
                    "descendants": "/rest/api/content/123456789/descendant",
                    "space": "/rest/api/space/MYSPACE"
                }
            },
            {
                "id": "567890123",
                "type": "page",
                "status": "current",
                "title": "FAQ",
                "extensions": {
                    "position": 1
                },
                "_links": {
                    "webui": "/display/MYSPACE/FAQ",
                    "edit": "/pages/resumedraft.action?draftId=567890123",
                    "tinyui": "/x/HQD2Mw",
                    "self": "https://wiki.abc.com/rest/api/content/567890123"
                },
                "_expandable": {
                    "container": "/rest/api/space/MYSPACE",
                    "metadata": "",
                    "operations": "",
                    "children": "/rest/api/content/567890123/child",
                    "restrictions": "/rest/api/content/567890123/restriction/byOperation",
                    "history": "/rest/api/content/567890123/history",
                    "ancestors": "",
                    "body": "",
                    "version": "",
                    "descendants": "/rest/api/content/567890123/descendant",
                    "space": "/rest/api/space/MYSPACE"
                }
            }
        ],
        "start": 0,
        "limit": 25,
        "size": 2,
        "_links": {
            "self": "https://wiki.abc.com/rest/api/content/998877665/child/page"
        }
    },
    "_links": {
        "base": "https://wiki.abc.com",
        "context": "",
        "self": "https://wiki.abc.com/rest/api/content/998877665/child"
    },
    "_expandable": {
        "attachment": "/rest/api/content/998877665/child/attachment",
        "comment": "/rest/api/content/998877665/child/comment"
    }
}

TypeScript: WikiTree.ts

export interface WikiTree {
    page: Page;
    _links: Links;
    _expandable: Expandable;
  }
  export interface Page {
    results?: (ResultsEntity)[] | null;
    start: number;
    limit: number;
    size: number;
    _links: Links1;
  }
  export interface ResultsEntity {
    id: string;
    type: string;
    status: string;
    title: string;
    extensions: Extensions;
    _links: Links2;
    _expandable: Expandable1;
  }
  export interface Extensions {
    position: number;
  }
  export interface Links2 {
    webui: string;
    edit: string;
    tinyui: string;
    self: string;
  }
  export interface Expandable1 {
    container: string;
    metadata: string;
    operations: string;
    children: string;
    restrictions: string;
    history: string;
    ancestors: string;
    body: string;
    version: string;
    descendants: string;
    space: string;
  }
  export interface Links1 {
    self: string;
  }
  export interface Links {
    base: string;
    context: string;
    self: string;
  }
  export interface Expandable {
    attachment: string;
    comment: string;
  }

Я быхотел бы заполнить массив children вызовом службы на основе его родителя result.id

Пример: вызов был бы функцией в Wiki Service, которая возвращает наблюдаемый.

this.wikiChildTree$ = this.wikiService.GetWikiHierarchy(result.id);

Из данных, возвращаемых в наблюдаемой wikiChildTree$, я хотел бы создать массив объектов title и link.Таким образом, массив объектов infoCards будет отражать объект JSON, подобный следующему:

[{
        "image": "",
        "title": "Start here",
        "titleLink": "/page/wiki/123456789",
        "children": [{
            "title": "Storm",
            "link": "/page/wiki/660431"
        },
        {
            "title": "Weather",
            "link": "/page/wiki/660432"
        }]
},
{
        "image": "",
        "title": "FAQ",
        "titleLink": "/page/wiki/567890123",
        "children": [{
            "title": "Cloud",
            "link": "/page/wiki/450433"
        },
        {
            "title": "Sunshine",
            "link": "/page/wiki/120432"
        }]
}
]

Это похоже на выполнение асинхронного вызова родительского потомка для получения дочерних данных.

Я читал оforkjoin и mergemap, но не уверены насчет реализации здесь.Как я могу это сделать?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Добавлены возвратные данные в ответ Амира, чтобы избавиться от ошибок.Функция map, необходимая для возврата наблюдаемой типа wikiTree.

ngOnInit() {
       this.wikiTree$ = this.wikiService.GetWikiHierarchy().pipe(
          switchMap(data => 
             forkJoin(data.page.results.map(result => this.wikiService.GetWikiHierarchy(result.id))).pipe(
                map(children => ({data, children}))
             )
          )
       ).subscribe((data, children) => {
            const newInfoCards = data.page.results.map((result, i) => (
            {
              "image": "",
              "title": result.title,
              "titleLink": "/page/wiki/"+ result.id,
              "children": children[i]
            }))
            this.infoCards = [...this.infoCards,...newInfoCards]
            return data
          },
          (err) => {
            console.log(err);
          }
       );
}
0 голосов
/ 04 февраля 2019

Таким образом, в основном вы должны быть в состоянии сделать это следующим образом:

ngOnInit() {
       this.wikiTree$ = this.wikiService.GetWikiHierarchy().pipe(
          switchMap(data => 
             forkJoin(data.page.results.map(result => this.wikiService.GetWikiHierarchy(result.id))).pipe(
                map(children => ({data, children}))
             )
          )
       ).subscribe(({data, children}) => {
            const newInfoCards = data.page.results.map((result, i) => (
            {
              "image": "",
              "title": result.title,
              "titleLink": "/page/wiki/"+ result.id,
              "children": children[i]
            }))
            this.infoCards = [...this.infoCards,...newInfoCards]
          },
          (err) => {
            console.log(err);
          }
       );
}

Объяснение:

  1. Вы загружаете this.wikiService.GetWikiHierarchy () ;
  2. Вы загружаете все this.wikiService.GetWikiHierarchy (result.id) для каждого результата одновременно, используя forkJoin.
  3. Загруженные вами данные из обоих мест отображаются в объект {data, children} , где data - результат первого вызова children - результат второго forkJoin (массив потомков или потомков [] []) .
  4. После этого вам нужно объединить data.page.results с children (который является массивом массивов) .Надеюсь, это поможет.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...