"Combine JSON data using an observable based on the ID field

Consider two distinct REST services in my project:

todo.service.ts
user.service.ts

Below are the properties defining each object:

todo: userId, title, id, completed
user: id, name, email, etc

Both services return an Observable with collections conforming to these definitions.

users: Observable<User[]>
todos: Observable<Todo[]>

The desired output format looks like this:

todo.title by user.name

What would be the most optimal approach to achieve this? Should I merge them into one combined object like so:

todo: id, title, completed, user { id, name, email, etc }

Alternatively, is there a better strategy to accomplish this?

Any insights or suggestions would be greatly appreciated. Thank you!

Answer №1

After examining your implementation, I noticed a few things that seemed off to me, so I made some changes and will explain them.

In your services, it's better to create a separate function to return the observable instead of doing it within the constructor. This allows you to delay fetching the data or refresh using the same function. Here is an example (make similar changes in other services):

@Injectable()
export class UserService {

  private API = 'https://jsonplaceholder.typicode.com/users';

  constructor(private httpClient: HttpClient) { }

  getUsers() {
    return this.httpClient.get(this.API);
  }
}

Next, in the component, create two lists that can be manually updated using a promise, or subscribed to an observable for dynamic changes.

export class AppComponent {
  name = 'Angular';
  todos:[];
  users:[];

  constructor(
    private todoService: TodoService,
    private userService: UserService
  ) {
    this.getUsers();
    this.getTodos();
  }

  getTodos() {
    // Fetch todos only once using promises
    this.todoService.getToDos().toPromise().then(todos => {
      this.todos = todos;
    });
  }

  getUsers() {
    // Fetch users only once using promises
    this.userService.getUsers().toPromise().then(users => {
      this.users = users;
    });
  }

  getUsername(id) {
    if (this.users && this.users.length > 0) {
      return this.users.find(user => {
        return user.id === id;
      }).name;
    }
  }
}

Lastly, here is the corresponding HTML code:

<h3>Users</h3>
<ul>
  <li *ngFor="let user of users">{{ user.name }}</li>
</ul>

<h3>Todos</h3>
<ul>
  <li *ngFor="let todo of todos">{{ todo.title }} ({{ getUsername(todo.userId) }})</li>
</ul>

This setup results in the following output:

Users

  • Leanne Graham
  • Ervin Howell
  • Clementine Bauch
  • Patricia Lebsack
  • Chelsey Dietrich
  • Mrs. Dennis Schulist
  • Kurtis Weissnat
  • Nicholas Runolfsdottir V
  • Glenna Reichert
  • Clementina DuBuque

Todos

  • delectus aut autem (Leanne Graham)
  • quis ut nam facilis et officia qui (Leanne Graham)
  • fugiat veniam minus (Leanne Graham)
  • et porro tempora (Leanne Graham)
  • laboriosam mollitia et enim quasi adipisci quia provident illum (Leanne Graham)
  • qui ullam ratione quibusdam voluptatem quia omnis (Leanne Graham)
  • illo expedita consequatur quia in (Leanne Graham)

and so on.

Is mapping them to one single object the best approach?

I recommend against it because maintaining them separately allows for more flexibility - one list can change independently of the other.

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

Understanding the significance of "this" within node.js modules and functions

Upon using the require method, a JavaScript file is loaded. The code snippet demonstrates an interesting scenario where this behaves differently within different parts of the script. // loaded by require() var a = this; // "this" here refers to an empty ...

Increase numbers with uniform speed using jQuery for each number

I am working on implementing a jQuery script that will visually increase any number from zero to its value using setInterval(). Here is the current solution I have come up with: $('.grow').each(function() { var $el = $(this); va ...

The output display is not visible

I am currently working on a tutorial to showcase contact details on my webpage. However, I am facing an issue where the code is not displaying the first and last name as expected. Below is the code snippet for reference. Snippet from index.html <!DOCT ...

Hiding a parent DIV in JS based on specific content: Here's how

I need help figuring out how to hide multiple parent DIVs based on the content of a specific child DIV. Here's an example: <div class="report-per-day"> <div class="report-day">26 May 2022</div> <div class=" ...

Populating Redux form fields with data retrieved from API call

Currently, I am working on an address finder component in React and I am looking for the most effective way to update the fields with values once I receive the data from the API. I am using a fetch in React to fetch the data and fill in some form fields, t ...

A guide to implementing Vuex in a Laravel and Vue 3 project

Currently, I am working on a Laravel + Vue 3 project and need to incorporate Vuex into the project. In my store.js file, I have configured my Vuex as shown below: import { createApp } from 'vue' import { createStore } from 'vuex' const ...

Embracing the node mindset with a Java foundation

As a Java Developer, I have become accustomed to working in a sequential manner where tasks are executed one after the other or concurrently with multiple threads. The organization of code in a sequential way seemed logical under this paradigm. However, wh ...

What is the method for retrieving a value with a designated key?

An array has been created from JSON source using the $.each method. The console displays the following: $vm0.sailNames; [Array(24), __ob__: Observer] (Interestingly, jQuery seems to have created an Observer) In the Vue.js development view, it appears li ...

Convert Python strings into HTML JavaScript blocks using Jinja2

Having trouble passing a string to an HTML page in the "<script>" block. I am currently using Python, Flask, and Jinja2. Python code: def foo(): return myString #"[{title: 'Treino 7-Corrida',start: '2015-12-08',color: '#d ...

Display a loading icon during the process of uploading files

I've created a multipart/form-data form that is targeted to an iframe. Check it out below: <form id="uploadForm" method="post" action="sample.jsp" name="uploadForm" enctype="multipart/form-data" target="fileUploadFrame"> <input type=" ...

Clicking on an element will remove a class and unselect an input using JQuery

Trying to achieve a functionality where clicking on a list item with a radio button input selects it, but clicking again deselects it. The issue is despite various attempts, nothing seems to work properly. function setupToptions() { if ($('ul.top ...

Updating the label on a Highcharts speedometer gauge

I need to customize the number sequence of a speedometer displaying internet bandwidth speed. I have done extensive research but haven't found a solution yet. Below is the code snippet for the highchart gauge. The current label sequence is 0,10,20,30 ...

Ways to execute multiple queries in ReactJS using AWS Amplify

I'm having trouble querying multiple Dynamo databases in React.js. I initially attempted to define each component in separate classes and import them, but that didn't work. Then I tried defining both components in the same class, which resulted i ...

What is the issue with this asynchronous function?

async getListOfFiles(){ if(this.service.wd == '') { await getBasic((this.service.wd)); } else { await getBasic(('/'+this.service.wd)); } this.files = await JSON.parse(localStorage.getItem('FILENAMES')); var ...

Struggling with implementing jquery Ajax and a php script to fetch information from a mysql database

I'm encountering issues with my current web app project in displaying a simple jpg image based on the selected radio button using jQuery AJAX along with a PHP script to interact with MySQL. Below is my ajax.js file: $('#selection').change( ...

How can an accordion icon be added and list toggling be accomplished when HTML data is sourced from an API instead of a JSON response?

I have an API that sends HTML data as a response. The task at hand is to add accordion icons to the items in the list and enable list toggling using HTML, CSS, JavaScript, React, and MaterialUI. Unfortunately, I am limited in my options and cannot use JQ ...

The error message thrown states: "Invalid function for Dispatch Action within Redux Toolkit."

Currently, I am in the process of learning the redux toolkit and have encountered a Type Error that I am unable to resolve. Let's Create a Counter Slice! const { createSlice } = require("@reduxjs/toolkit"); const initialState = { count ...

Display images next to each other with no need for a scroll bar

I'm currently developing a Roulette website and I am struggling to make the roulette animation function properly. I have an image for the roulette wheel, but I need the image to vanish after reaching a certain point and then loop around to the left. ...

The functionality to deselect multiple options in a select box is not functioning properly

There seems to be an issue with removing the selected attribute from the selected values in a jQuery multiselect box. The console is not showing any errors. You can view a working example here The problem lies in this code snippet: $("#mltyslct option ...

Enhance your HTML rendering with Vue.js directives

Check out this cool code example I created. It's a simple tabs system built using Vue.js. Every tab pulls its content from an array like this: var tabs = [ { title: "Pictures", content: "Pictures content" }, { title: "Music", c ...