Create a custom template needed by an Angular module using data from a JSON reply

I received JSON data from my API endpoint with a specific structure:

[
    {
      "id": 1,
      "title": "Smells like",
      "object": "",
      "children": [
        {
          "id": 2,
          "title": "Liquid",
          "object": {
            "objectid": 1,
            "title": "My object also have children",
            "children": []
          },
          "children": [
            {
              "id": 3,
              "title": "Loyal",
              "object": "",
              "children": []
            },
            {
              "id": 4,
              "title": "Smart",
              "object": "",
              "children": [
                {
                  "id": 5,
                  "title": "Smart",
                  "object": "",
                  "children": []
                }
              ]
            }
          ]
        },
        {
          "id": 6,
          "title": "Just empty",
          "object": {
            "objectid": 2,
            "title": "Title of my object",
            "children": []
          },
          "children": []
        }
      ]
    },
    {
      "id": 10,
      "title": "Apple",
      "object": "",
      "children": [
        {
          "id": 11,
          "title": "Ink",
          "object": "",
          "children": []
        },
        {
          "id": 12,
          "title": "Whatever",
          "object": "",
          "children": []
        }
      ]
    }
  ]

To convert this JSON to a format compatible with the Angular component I am using, follow this structure:

[
  new Link({
    id: 1,
    label: "Smells like",
    title: "Smells like",
    object: "",
    children: [
      new Link({
        id: 2,
        label: "Liquid",
        title: "Liquid",
        object: {
          objectid: 1,
          title: "My object also have children",
          children: [],
        },
        children: [
          new Link({
            id: 3,
            label: "Loyal",
            title: "Loyal",
            object: "",
            children: [],
          }),
          new Link({
            id: 4,
            label: "Smart",
            title: "Smart",
            object: "",
            children: [
              new Link({
                id: 5,
                label: "test",
                title: "test",
                object: "",
                children: [],
              }),
            ],
          }),
        ],
      }),
      new Link({
        id: 6,
        label: "Just empty",
        title: "Just empty",
        object: { objectid: 2, title: "Title of my object", children: [] },
        children: [],
      }),
    ],
  }),
  new Link({
    id: 10,
    label: "Apple",
    title: "Apple",
    object: "",
    children: [
      new Link({ id: 11, title: "Ink", object: "", children: [] }),
      new Link({
        id: 12,
        label: "Whatever",
        title: "Whatever",
        object: "",
        children: [],
      }),
    ],
  }),
];

Some key points:

  1. The new structure wraps root and children nodes with a new Link()
  2. A label is added based on the title of each node
  3. Sometimes, other objects in the JSON might have children properties where a new link wrapper is not necessary.

If you need help converting the first JSON structure to the required format in TypeScript, feel free to ask!

Answer №1

If you're looking to create nodes using recursion, here's a helpful function:

const createLink = (itemList) => itemList.map(item => {
    new Link({
        id: item.id,
        label: item.label,
        title: item.title,
        object: item.object,
        children: item.children.length ? createLink(item.children) : []
    })
})

This function will loop through all the items in your response. When it encounters items with children, it will call itself recursively to iterate through those children. Make sure to add an empty array if there are no children present.

Another point to note is that there are children arrays within objects as well. To handle this, you can create a helper function like so:

const createLink = (itemList) => itemList.map(item => {
    new Link({
        id: item.id,
        label: item.label,
        title: item.title,
        object: createObject(item.object),
        children: createLink(item.children)
    })
})

const createObject = (object) => {
    return {
        objectid: object.objectid,
        title: object.title,
        children: createLink(object.children)
    }
}

In summary, the createLink function allows you to map through subscription items and create a new array. You can use it within your subscriptions like this:

this.someService().subscribe(response => {
  this.convertedTree = this.createLink(response));
}

Don't forget to define your Link class and update the functions accordingly for smooth execution. The updated code also includes checks for empty arrays or objects.

For further reference and implementation, check out the demo on StackBlitz: https://stackblitz.com/edit/angular-primeng-tree-node-bbrmgs?file=src%2Fapp%2Fapp.component.ts

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How do I properly type when extending Button and encountering an error about a missing component property?

Currently in the process of transitioning from MUI v3 to v4. My challenge lies with some Button components that are wrapped and have additional styling and properties compared to the standard Material UI Button component. Ever since upgrading to v4, I&apos ...

Utilizing Angular 2's ngModel feature for dynamic objects and properties

Within my TypeScript file, I am dynamically generating properties on the object named selectedValsObj in the following manner: private selectValsObj: any = {}; setSelectedValsObj(sectionsArr) { sectionsArr.forEach(section => { section.questions. ...

Setting state dynamically in Typescript with ReactJS

Within my state, I have defined this interface: interface State { id: string; name: string; description: string; dimensionID: string; file: File | null; operator: string; isFormValid: boolean; filename: string; }; To handle changes, I&apo ...

Error encountered: Module 'redux-saga/effects' declaration file not found. The file '.../redux-saga-effects-npm-proxy.cjs.js' is implicitly typed as 'any'. Error code: TS7016

<path-to-project>/client/src/sagas/index.ts TypeScript error in <path-to-project>/client/src/sagas/index.ts(1,46): Could not find a declaration file for module 'redux-saga/effects'. '<path-to-project>/client/.yarn/cache/red ...

Experimenting with an API request in Angular 2

I have two components and a shared service between them. I want to unit test the dependencies of the service on these components, but I'm struggling to figure out how to do it effectively. //a.component.ts import { Component, Input } from '@angu ...

What could be the reason for receiving 'undefined' in TypeScript after saving data in a variable?

When working on my program, I encountered an issue where I am trying to create a service and declare a variable within the service. I then created a get() method in the service to print the variable by calling the service method from a component, but I k ...

A comprehensive guide on utilizing the loading.tsx file in Next JS

In the OnboardingForm.tsx component, I have a straightforward function to handle form data. async function handleFormData(formData: FormData) { const result = await createUserFromForm( formData, clerkUserId as string, emailAddress a ...

Angular: efficient exchange of information among components

I have a component X that handles a WebSocket. And within component X, I also have multiple presentation components (e.g. Y). Whenever the WebSocket receives a specific message, I need to perform an action in a particular component (e.g. refresh data). To ...

The functionality of allowEmpty : true in gulp 4.0 does not seem to be effective when dealing with

gulp.task("f1", () => { gulp.src([], {"allowEmpty": true}) .pipe(gulp.dest(location)); }) An error message pops up saying "Invalid glob argument:" when the code above is used. gulp.task("f1", () => { gulp.sr ...

Angular click event to compute a function and display the result on a separate page

Currently, I am developing a BMI app using Ionic Angular (latest version). The objective is to create a button that collects input data from fields and triggers a method to validate the inputs. Once validated, the app should display the results page with t ...

The Angular CLI seems to be having trouble locating modules that are clearly present within the workspace

After deleting a component and recreating it with the same name and folder structure using the CLI, I encountered an error. The CLI began throwing errors stating it couldn't find modules that were clearly present and untouched. These modules are simpl ...

Single instance property binding for Angular

I am looking for a solution to set the checked attribute of a checkbox only once, based on whether the current object is in an array. I want this check to happen during initial render and not rely on change detection. <input type="checkbox" [c ...

Error TS2307: Module 'passport' is nowhere to be found

Recently, I ventured into a new project using the TypeScript Basic Node.js Express 4 Application template in VS 2017. To enhance my project, I utilized npm to add passport. The addition of passport is reflected under the npm node in Solution Explorer, wit ...

Setting `throwIfNamespace=true` in the `.babelrc` file for a `create-react-app` project

Running into a bit of a snag here. I thought setting up a simple app would be smooth sailing, but it seems that's not the case. I created an app using the latest create-react-app and decided to add a <gcse:search> tag. However, I encountered the ...

Troubleshooting Cross-Origin Resource Sharing problem in .NET 6 when integrating with IONIC/Angular

Despite configuring all the necessary CORS settings for the .NET 6 backend, I am still unable to access the endpoints using IONIC/Angular service. Here is a snippet of my backend code (which functions correctly in Postman): Some example Controller Method ...

OnPush strategy and template updates: Propagating modifications to the parent component

I am currently facing an issue with a parent component that consists of two templates. The first template simply displays data-bound text, while the second template contains a child component responsible for updating the data model. Both the parent and chi ...

Managing the onChange event for a MaterialUI dropdown component

I'm encountering an issue with validating the MaterialUI TextField component (Country list) wrapped with Autocomplete. I am trying to use the onChange event to enable the Submit button when the country field is filled in. However, the problem arises w ...

Error encountered following repo duplication

Recently, I upgraded to a new workstation and decided to clone my Angular4 Project repo onto it. After completing the cloning process, I executed: npm install This command is used to fetch all the required node_modules, leading to a multitude of missing ...

Issues with Typescript and TypeORM

QueryFailedError: SQLITE_ERROR: near "Jan": syntax error. I am completely baffled by this error message. I have followed the same steps as before, but now it seems to be suggesting that things are moving too slowly or there is some other issue at play. ...

The combination of ampersand with JSON and Angular6 creates a powerful

I am facing an issue with the ampersand while trying to build the URL for my service: addPost(post: Post){ let json = JSON.stringify(post); //let params = 'json='+json.replace('&','y'); let params ...