Display sub-objects within Chart.js

I'm currently tackling a project in Ionic 3 where I am utilizing an API that returns a JSON response with nested objects. My goal is to display certain aspects of these objects within a bar graph using chart.js.

Unfortunately, I lack experience in manipulating JSON objects.

{
"fruits": [
    {
    "oranges": {
      "good": 1,
      "not_good": 0
    },
    "apples": {
      "good": 1,
      "not_good": 0
    },
    "grapes": {
      "good": 2,
      "not_good": 0
    }
  }]
 }

It's uncertain how many fruits will be included in the response.

The names of the fruits would serve as the labels for the graph, while the 'good' and 'not good' values would make up the datasets.

Answer №1

const healthyFruits = []; 
const unhealthyFruits = [];
const fruitLabels = [];
for (let index = 0; index < obj.fruits.length; index++) {
    const fruitObj = obj.fruits[index];
    // Iterate through the keys of each fruit object to determine its health status
    for (var property in fruitObj) {
        // Record the fruit name
        fruitLabels.push(property);
        let value = fruitObj[property];
        if(value.good == 1) {
            // If good is 1, add the fruit name to healthyFruits array
            healthyFruits.push(value);
        } else {
            // If bad is 1, add the fruit name to unhealthyFruits array
            unhealthyFruits.push(value);
        }
    }
}

Answer №2

Creating a bar chart using Chart.js entails the following steps:

var ctx = document.getElementById("myChart").getContext("2d");

var data = {
  labels: ["Good", "Not good"],
  datasets: [{
    label: "Oranges",
    backgroundColor: "orange",
    data: [2, 1]
  }, {
    label: "Apples",
    backgroundColor: "green",
    data: [4, 2]
  }, {
    label: "Grapes",
    backgroundColor: "purple",
    data: [3, 1]
  }]
};

var myBarChart = new Chart(ctx, {
  type: 'bar',
  data: data,
  options: {
    barValueSpacing: 20,
    scales: {
      yAxes: [{
        ticks: {
          min: 0
        }
      }]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js"></script>
<canvas id="myChart" width="400" height="400"></canvas>

To adjust the data received from an API to fit the required format for the chart, you can manipulate the data as follows:

const res = {
  fruits: [
    {
      oranges: {
        good: 1,
        not_good: 0
      },
      apples: {
        good: 1,
        not_good: 0
      },
      grapes: {
        good: 2,
        not_good: 0
      }
    }
  ]
};
const dataset = Object.entries(res.fruits[0]).map(fruit => {
  return {
    label: fruit[0],
    data: Object.values(fruit[1])
  };
});

console.log(dataset);

Additionally, if the background colors for each bar are not provided by the API, you will need to determine where to source this information.

Here is how everything comes together in the final implementation:

const res = {
  fruits: [
    {
      oranges: {
        good: 10,
        not_good: 5
      },
      apples: {
        good: 6,
        not_good: 1
      },
      grapes: {
        good: 9,
        not_good: 5
      },
      pears: {
        good: 15,
        not_good: 6
      }
    }
  ]
};

const datasets = Object.entries(res.fruits[0]).map(fruit => {
  return {
    label: fruit[0], 
    data: Object.values(fruit[1]),
    backgroundColor: getRandomColor()
  };
});


const ctx = document.getElementById("myChart").getContext("2d");

const data = {
  labels: ["Good", "Not good"],
  datasets
};

const myBarChart = new Chart(ctx, {
  type: 'bar',
  data: data,
  options: {
    barValueSpacing: 20,
    scales: {
      yAxes: [{
        ticks: {
          min: 0
        }
      }]
    }
  }
});

function getRandomColor() {
  const letters = '0123456789ABCDEF';
  let color = '#';
  for (let i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js"></script>
<canvas id="myChart" width="400" height="400"></canvas>

View JSfiddle Example

Reference to getRandomColor Implementation

Answer №3

If you want to transform your object into an array of fruit objects, consider the following approach:

const data = {
 "fruits": [
   {
    "oranges": {
      "good": 1,
      "not_good": 0
    },
    "apples": {
      "good": 1,
      "not_good": 0
    },
    "grapes": {
      "good": 2,
      "not_good": 0
    }
   }]
 };

 const result = Object.keys(data.fruits[0])
 .map(fruit => ({'name': fruit, 'values': data.fruits[0][fruit] }));

 console.log(result);
 

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

When defining functions in Typescript, the new() syntax is used

Can you explain the purpose of the type declaration for dialogComponent in this specific Typescript code snippet? createDialog(dialogComponent: { new(): DialogComponent }) : Promise<ComponentRef<DialogComponent>> { ... } (Referenced from ...

Tips for integrating Reactjs with Chessboard.js

Recently, I stumbled upon chessboardjs (https://chessboardjs.com/) as a way to hone my React coding skills. However, I hit a roadblock while trying to implement a simple example of displaying the chess board in my application. The documentation instructed ...

Tips for enabling resize functionality on individual components one at a time

Check out my Codepen link for the resizable event While using Jquery UI resizable, everything is functioning correctly. However, I am now looking to have the resizable event activate one block at a time. When another block is clicked, the resizable event ...

Looking to adjust the height of a foreignObject element within an SVG?

Looking to dynamically change the height of a foreignObject within an SVG, while also needing HTML elements inside it (working with ngx-graph). <foreignObject x="1" y="1" width="335" [height]="foreignObjHeight(node.Dat ...

Creating custom functionality by redefining methods in Typescript

My current scenario is as follows: abstract class A implements OnInit{ ngOnInit() { this.method(); } private method() { // carrying out tasks } } class B extends class A implements OnInit { ngOnInit() { thi ...

Generating a random number to be input into the angular 2 form group index can be done by following these

One interesting feature of my form is the dynamic input field where users can easily add more fields by simply clicking on a button. These input fields are then linked to the template using ngFor, as shown below: *ngFor="let data of getTasks(myFormdata); ...

Simulating server-side interactions in Node.js with TestCafe

I am currently working on a project where I need to figure out how to mock server-side requests. While I have successfully managed to mock client-side requests using request hooks, I am facing challenges when it comes to intercepting server-side requests ...

Error: Property 'content' is not defined and cannot be read

I encountered an issue with a config file while attempting to build with AOT using the command ionic cordova build android --prod Error: ./src/config/.env.ts Module build failed: TypeError: Cannot read property 'content' of undefined at Object ...

What steps are involved in adding an image to an autocomplete script?

I need help adding an image to my autocomplete script. Below is my code that I'm struggling with. My Controller: function getsearch($c_id) { $searchTerm = $_GET['term']; $query = $this->db->query("SELECT state_name FROM state ...

Priority is given to strings over numbers

Here's some code I'm working with: <tbody> <tr> <td class="float-left"> <!-- {{selectedTemplat?.modifiedAt | da ...

Comprehending the significance of *this* within class structures

I've got this code snippet below. class Node { constructor(value, parent, possibleChildren = []) { this.value = value; this.parent = parent; this.children = [] this.setChildren(possibleChildren); } setChildren(possibleChil ...

Enhancing jQuery Mobile listview with voting buttons on each item row

I am looking to incorporate 2 vote buttons within a jQuery mobile listview, positioned on the left-hand side and centered within each list item. While I have managed to achieve this using javascript, my goal is to accomplish it without any additional scrip ...

Can someone guide me on how to use contract.on() in ethers.js to listen to events from a smart contract in a node.js application?

I've been working on a node.js application using ethers.js to listen to events emitted from the USDT contract Transfer function. However, when I run the script, it exits quickly without displaying the event logs as expected. I'm unsure of what st ...

Error message: Unable to assign value to 'kind' property as it is undefined in Angular Webpack application

Unexpectedly, my Angular application is encountering an error during the build process. TypeError: C:\Users\c\dev\privacy\node_modules\@fortawesome\angular-fontawesome\fesm2020\angular-fontawesome.mjs: Cannot se ...

Is it possible to use cakephp and AJAX to determine if a table is empty?

Is there a way to determine if a table is empty using CakePHP and AJAX? In my index.ctp, I have included an image that, when clicked, will notify the user about the status of the table. If the table is empty, an alert box will pop up; otherwise, the user w ...

React.js with Typescript is throwing an error stating that a property does not exist on the child component

Currently, I am working with React in conjunction with typescript 2.3.4. I keep encountering the error TS2339: Property 'name' does not exist on type 'Readonly<{ children?: ReactNode; }> & Readonly<{}>'. This issue arises when attemptin ...

Build an Angular wrapper component for the phone textbox functionality

Looking to transform the Phone Mask solution below into an Angular component. Does anyone have a method to accomplish this? * Any solution that results in a similar component for a Phone textbox will suffice. Mask for an Input to allow phone numbers? ht ...

Utilizing Angular for Webcam Integration

After trying out this code snippet: <video autoplay playsinline style="width: 100vw; height: 100vh;"></video> <script> navigator.mediaDevices.getUserMedia({ video: { facingMode: 'user' } }) .then(stream =&g ...

How to retrieve document.getElementsByName from a separate webpage using PHP and javascript

Hey there, I've been searching for a solution to this issue but haven't had any luck so far. I'm attempting to retrieve the value of the name test from an external website. <input type="hidden" name="test" value="ThisIsAValue" /> Up ...

Mastering the art of invoking a JavaScript function from a GridView Selected Index Changed event

In my current setup where I have a User Control within an Aspx Page and using Master Page, there's a GridView in the User Control. My goal is to trigger a javascript function when the "Select" linkbutton on the Gridview is clicked. Initially, I succe ...