amChartv5 on Angular is successfully displaying a Gantt chart that includes multiple categories with the same name being resolved

I've been working on integrating an amCharts v5 gantt chart with Angular 13. Each bar in the chart represents a project, and if there are multiple occurrences of a category, they should stack like a timeline. I've successfully retrieved data from a local JSON file and added custom properties. However, I'm facing an issue where the chart creates multiple lines for each declaration, even when the categories match.

It's worth noting that the bars stack correctly, with all the inputs in sequence as intended. The problem lies in the chart creating three lines, two of which are empty, while only the third is populated by the data as expected.

Here is an example of the JSON structure:

[
    {
      "category": "LETICIA",
      "fromDate": "2022-08-02 00:00",
      "toDate": "2022-08-08 23:59",
      "columnSettings": {
        "fill": "#57315b"
      },
      "task": "Sprint #1",
      "personnel": 13
    },
    {
      "category": "LETICIA",
      "fromDate": "2022-08-08 00:00",
      "toDate": "2022-08-09 23:59",
      "columnSettings": {
        "fill": "#E6E6FA"
      },
      "task": "Presentation",
      "personnel": 14
    },
    {
      "category": "LETICIA",
      "fromDate": "2022-08-09 00:00",
      "toDate": "2022-08-19 23:59",
      "columnSettings": {
        "fill": "#57315b"
      },
      "task": "Sprint #1",
      "personnel": 15
    }
]

View the resulting chart here

I have attempted to manipulate the JSON data without much success. Is there a way to eliminate these unnecessary category duplications?

Unfortunately, I haven't been able to adapt it for StackBlitz yet, but you can view my current component and service setup here: Check out my code on StackBlitz

Answer №1

The issue in your code can be found on line 95: yAxis.data.setAll(data);

Instead of using the variable data, which contains repeated categories, you need to pass an array of object literals that specifically lists your categories like this:

yAxis.data.setAll([
  { category: "Category 1" },
  { category: "Category 2" },
  { category: "Category 3" }
]);

Here is a complete example:

am5.ready(() => {

  let root = am5.Root.new("chartdiv");

  let chart = root.container.children.push(am5xy.XYChart.new(root, {}));
  
  let data = [
    {
      "category": "LETICIA",
      "fromDate": "2022-08-02 00:00",
      "toDate": "2022-08-08 23:59",
      "columnSettings": {
        "fill": "#57315b"
      },
      "task": "Sprint #1",
      "personnel": 13
    },
    {
      "category": "LETICIA",
      "fromDate": "2022-08-08 00:00",
      "toDate": "2022-08-09 23:59",
      "columnSettings": {
        "fill": "#E6E6FA"
      },
      "task": "Presentation",
      "personnel": 14
    },
    {
      "category": "LETICIA",
      "fromDate": "2022-08-09 00:00",
      "toDate": "2022-08-19 23:59",
      "columnSettings": {
        "fill": "#57315b"
      },
      "task": "Sprint #1",
      "personnel": 15
    }
  ];

  let xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, {
    baseInterval: { timeUnit: "minute", count: 1 },
    renderer: am5xy.AxisRendererX.new(root, {})
  }));
  
  let yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
    categoryField: "category",
    renderer: am5xy.AxisRendererY.new(root, { inversed: true })
  }));

  // ==================================================
  yAxis.data.setAll([{ category: "LETICIA" }]); // <--- HERE
  // ==================================================

  let series = chart.series.push(am5xy.ColumnSeries.new(root, {
    xAxis: xAxis,
    yAxis: yAxis,
    openValueXField: "fromDate",
    valueXField: "toDate",
    categoryYField: "category"
  }));

  series.columns.template.setAll({
    templateField: "columnSettings",
    strokeOpacity: 0
  });

  series.data.processor = am5.DataProcessor.new(root, {
    dateFields: ["fromDate", "toDate"],
    dateFormat: "yyyy-MM-dd HH:mm"
  });
  
  series.data.setAll(data);

});
#chartdiv {
  width: 100%;
  height: 350px;
}
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>

<div id="chartdiv"></div>

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

Ways to use DecimalPipe for rounding numbers in Angular - Up or down, your choice!

Looking to round a number up or down using DecimalPipe in Angular? By default, DecimalPipe rounds a number like this: Rounding({{value | number:'1.0-2'}}) 1.234 => 1.23 1.235 => 1.24 But what if you want to specifically round up or do ...

Shared validation between two input fields in Angular 2+

I have a unique task at hand. I am working on creating an input field with shared validation. The goal is to ensure that both fields are technically required, but if a user fills in their email address, then both fields become valid. Similarly, if they ent ...

A section of the URL path has been deleted, leading to a repetitive cycle of clicking back and forth in

While using the navigate function of Router in angular, I encountered a strange issue. It seems that when I navigate once, it actually creates two navigations in history. Additionally, the URL is automatically updated with part of the URL being stripped of ...

The CSS properties intended for ion-button elements are not taking effect

I'm attempting to set a background color when a ion-button is clicked or maintain the ion-ripple effect after it has filled the button in Ionic 4. I experimented with applying custom CSS states in global.scss, but encountered issues where the active ...

Disable and grey out the button while waiting for the Observable to broadcast successfully

component.html <button mat-raised-button color="primary" type="submit"> <mat-icon>account_box</mat-icon> <span *ngIf="!loading">&nbsp;&nbsp;&nbsp;Register</span> <span * ...

Encountering the error message "TypeError: Cannot access property 'Token' of undefined" while compiling fm.liveswitch

The fm.liveswitch JavaScript Software Development Kit (SDK) is designed for use with both clients and your own backend "app server". It functions smoothly in the frontend thanks to webpack and babel. However, the same import statement: import liveswitch fr ...

Struggling to integrate authentication and authorization features into a ReactJS application with Microsoft Azure AD or Database login functionality

We have an application built on React v18 with a backend that includes a Web API and SQL Server database. Our requirement is to authenticate and authorize users using either MS Azure AD or the database. If a user attempts to log in with a username and pas ...

When the first argument is missing, using a recursive constraint default can result in the incorrect inference of the second argument, especially when both arguments share the same generic

Currently, I am developing a TypeScript implementation of a recursive binary search tree (BST) data structure using generic constraints. In order to establish a default for the recursive generic variable T without directly using it in the default declarati ...

What steps can I take to ensure TypeScript compiler approves of variance in calling generic handlers, such as those used in expressJS middleware?

disclaimer: I am a bit uncertain about variance in general... Here is the scenario I am facing: // index.ts import express from 'express'; import {Request, Response} from 'express'; const app = express(); app.use(handler); interface ...

Perform a child component function in Angular

I'm working on a project with a child component as a map and a parent component as a form. The parent component has a field for writing the address, and when an address is entered, an HTTP request is triggered to find the latitude and longitude coordi ...

Optimal approach for designing interfaces

I have a situation where I have an object retrieved from the database, which includes assignee and author ID properties that refer to user objects. As I transform a number into a user object, I am unsure about the best practice for defining the type of the ...

Issue with Validators in Model-driven Forms

Currently conducting testing on a basic application. These are the files in use: home.component.ts import { Component } from '@angular/core'; import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms'; @Componen ...

Navigating the use of property annotations in Mapped Types with remapped keys

After exploring the concept of Key Remapping in TypeScript, as shown in this guide, I am wondering if there is a way to automatically inherit property annotations from the original Type? type Prefix<Type, str extends string> = { [Property in keyo ...

Identifying browser compatibility for date input type with Angular 2 and above

Is there a reliable method to check if the browser supports <input type="date"> in Angular2+? I came across a suggestion on https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date where they recommend creating the input element and chec ...

The term "Movie" is not compatible as a JSX component

Currently working on a movie app project but encountering issues with handling arguments and displaying them properly using TypeScript. The challenge lies in trying to map the movie object, display them individually on the homepage, and showcase all the re ...

What exactly do Dependencies mean in Angular?

As a beginner in Angular, the concept of dependencies has come up several times during my learning process. Despite my efforts to search for a clear definition of Dependencies in Angular on Google, I have been unsuccessful. Could someone please provide a ...

Developing with Ionic 2 allows you to efficiently run a background service using Cordova

I am currently using Ionic 2 and I have a requirement for my app to perform certain tasks even when it is closed, similar to how Gmail continues to provide notifications all the time. After some research, I came across this documentation: https://ionicfr ...

TypeScript functions with Generic Constraints return specific values rather than just types

function createGenericCoordinates<Type extends number | string>( x: Type, y: Type ) { return { x, y }; } const genericCoordinates = createGenericCoordinates(1, 2); // Error (TS2322) // Type 3 is not assignable to type 1 | 2 genericCoordinates ...

What could be causing the error in Angular 2 when using multiple conditions with ng-if?

My aim is to validate if the length of events is 0 and the length of the term is greater than 2 using the code below: <li class="more-result" *ngIf="events?.length == 0 && term.value.length > 2"> <span class="tab-content- ...

Setting an expiry date for Firestore documents

Is it feasible to set a future date and time in a firestore document and trigger a function when that deadline is reached? Let's say, today I create a document and specify a date for the published field to be set to false fifteen days later. Can this ...