Adding CSS classes to labels in Angular using D3

Within my Angular v14 project, I am utilizing D3 v7 to create a captivating donut chart featuring two distinct styles of labels. Here's a visual representation: https://i.sstatic.net/tTegv.png

The following code snippet showcases how I incorporate bold labels:

  this.svg
  .selectAll("allLabels")
  .data(data_ready)
  .enter()
  .append("text")
  .text((d:{data: NameValueColor}) => {
    return d.data.value.toString()+"%";
  })
  .attr("transform", (d: d3.DefaultArcObject) => {
    var pos = outerArc.centroid(d);
    var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
    pos[0] = this.radius * 0.95 * (midangle < Math.PI ? 1 : -1);
    pos[1] +=10;
    return "translate(" + pos + ")";
  })
  .attr("stroke", "#253b62")
  .style("font-weight", "500")
  //.attr("class","bold-label")
  //.class("bold-label")
  .attr("text-anchor", (d: d3.DefaultArcObject) => {
    var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
    return midangle < Math.PI ? "start" : "end";
  });

As illustrated, the font weight and color are defined within the code. However, my intention is to achieve this through my .scss file by implementing:

    .bold-label
    {
        color: "#253b62";
        font-weight:500;
    }

Despite attempting to use

.attr("class","bold-label")

neither the color nor the font-weight were applied successfully.

I also experimented with

.class("bold-label")

This approach not only failed to apply the class but also caused misalignment of the % labels on the left-hand side.

In a further attempt, I introduced

::ng-deep 

followed by

encapsulation: ViewEncapsulation.None,

Regrettably, this adjustment did not yield the desired outcome. What would be the correct method for applying the class in this scenario?

Answer №1

After working closely with my friend, we were able to pinpoint the issue. It turns out that a

tag was being used where d3 requires a container to work its magic. To solve this problem, we needed to utilize an ng-deep in the component's scss file to apply the necessary class. This allowed us to overcome the encapsulation of the CSS class within the figure tag/component. I also made adjustments to the example code to align with your setup. Take a look at it here, and enjoy the results!</p>
<p><a href="https://stackblitz.com/edit/angular-d3-js-donut-chart-qttkmx?file=src%2Fapp%2Fd3-donut%2Fd3-donut.component.scss" rel="nofollow noreferrer">example component scss </a></p>
<pre><code>figure {
  ::ng-deep {
    .bold-label {
      fill: #555888;
      color: '#55588';
      font-weight: 800;
      font-size: 24px;
    }
  }
}

Wishing you success with your project!

Answer №2

Hey there! I managed to find a solution for the issue you were facing, and I took the liberty of creating a fork of your example:

https://stackblitz.com/edit/angular-d3-js-donut-chart-qttkmx?file=src%2Fstyles.css

In the component, I made some modifications in d3-donut.component which include:

// Add the polylines between chart and labels:
this.svg
  .selectAll("allLabels")
  .data(data_ready)
  .enter()
  .append("text")
  .text(d => {
    return d.data.name;
  })
  **.attr("class", d => {
    return 'super-class'
  })**
  .attr("transform", d => {
    var pos = outerArc.centroid(d);
    var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
    pos[0] = this.radius * 0.99 * (midangle < Math.PI ? 1 : -1);
    return "translate(" + pos + ")";
  })
  .style("text-anchor", d => {
    var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
    return midangle < Math.PI ? "start" : "end";
  });
}

.attr("class", d => { return 'super-class' }) By adding this line, I was able to apply the 'super-class' to all <text> tags. However, I encountered an odd behavior where defining the CSS class in d3-donut.component.scss file did not apply the style to the element. It worked perfectly when I declared the class in styles.css at the root level folder. You can observe this difference in the example provided. It seems like a CSS encapsulation problem, so feel free to define your d3 styles within #id container in styles.css. Best of luck!

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

In Next.js Typescript, the size of the final argument passed to useEffect was found to vary between renders

import dynamic from "next/dynamic" import React, { ReactNode } from "react"; type ButtonProps = { type: string, children: ReactNode, onClick: () => void } const ButtonWrapper: React.ComponentType<{}> = dynamic(() => ...

Streamline imports with Typescript

Is there a way to import modules with an alias? For example, I have an angular service in the folder common/services/logger/logger.ts. How can I make the import look like import {Logger} from "services" where "services" contains all my services? I've ...

Troubleshooting Problems with Angular Localization in EJ2 Syncfusion

I have been utilizing the Syncfusion Spreadsheet component to display data similar to an Excel spreadsheet. I successfully implemented all the necessary functionalities with Syncfusion documents, however, I am encountering a challenge. My current issue i ...

What could be the missing piece? The function is expected to provide a return value

Currently, I am developing a Typescript Express API and encountering an issue with one of my methods. The problem arises when trying to handle data received in a callback function. public async getAll(): Promise<GeneralResponse> { locationsRe ...

Issue encountered: Error message stating "Module not found: Error: Unable to locate 'classlist.js' in Angular CLI version 6.1.3"

When I run the ng build --watch command in the terminal, I encounter the following error: ERROR in ./src/polyfills.ts Module not found: Error: Can't resolve 'classlist.js' in 'E:\eclipse_dis_workspace\tourdubai\UI\s ...

Each element in ngFor triggers the invocation of ngAfterContentInit by Angular

In my Angular 11 (Ionic 5) app, I have a scenario with two components: A ContainerComponent and a BoxComponent. Both of these components are completely transparent (template: '<ng-content></ng-content>'). The challenge is for the cont ...

"Exploring the Power of RXJS Map and FlatMap for

I am relatively new to Angular 2 and RXJS Observables. I have been working on a task since this morning, and I have completed it. However, I am having trouble understanding how it actually works. Below is the content of my test.json file located in the As ...

When adding a package in Angular, the package.json file may not reflect the update

Why isn't my package.json file getting updated when I try to install a new package using npm install [package name] --save? This is the setup I have in my project: npm version 6.4.1 and Angular CLI version 6.1.4. https://i.sstatic.net/wUejO.png Thank ...

What is the best way to sort an array within an object?

I'm having difficulty filtering an array within an object based on a condition (specifically, filter if value1 <> value2 and toggle is true) myObject = { value: 1, capacitiesArray: [{value1: 10, value2: 10}, {value1: 10, value2: 20}] ...

Creating a blueprint for an object to be utilized in state within a TypeScript React application

Looking to establish the structure of an object for use in React state. The object is structured like this: { 1: [{foo: 'whatever', bar: 'another string'}], 2: [{foo: 'yet another string', bar: '...'}], . ...

Changing TypeScript Enum from String to Number in Angular

Does anyone know how to convert a Typescript enum value to a number for display in a dropdown but passing the numeric value on submit? Here is how the enum is currently set up: I am currently able to output the string key of the object when it is emitted ...

Move the vertex onto the mxGraph canvas using drag-and-drop functionality

Hey there, I'm currently working on dragging and dropping a vertex from the create button onto the mxGraph canvas, similar to how it's done in draw.io. This is what my TS code looks like: addShape(shape: string,event) { event.stopPropagation(); ...

What could be causing my Page to not update when the Context changes?

In my Base Context, I store essential information like the current logged-in user. I have a User Page that should display this information but fails to re-render when the Context changes. Initially, the Context is empty (isLoaded = false). Once the init fu ...

Error message displaying 'class-transformer returning undefined'

I'm new to working with the class-transformer library. I have a simple Product class and JSON string set up to load a Product object. However, I'm encountering an issue where even though I can see the output indicating that the transformation was ...

Activate Angular Material's autocomplete feature once the user has entered three characters

My goal is to implement an Angular Material Autocomplete feature that only triggers after the user has inputted at least three characters. Currently, I have it set up so that every click in the input field prompts an API call and fetches all the data, whic ...

Template containing an observable collection of observables

Since the title is not helping me achieve my goal, let me explain what I'm trying to accomplish. My objective is to show a list of items in the view, which are fetched asynchronously from the backend. The service I have has a method called fetchItems ...

Incorporate a JavaScript library into a personalized JavaScript file that is utilized within my Angular2 project

Integrating Machine Learning into my Angular2 project using the "synaptic.js" JavaScript library is my goal. After executing the command npm install synaptic --save I intend to execute a custom javascript file (myJsFile.js): function myFunction() { v ...

When utilizing a combination of generics in a Typescript mapped type, the resulting property type is not computed

In an attempt to create a versatile method that can handle a Mapped Type named QueryParamObject and partially read its properties: QueryParamObject can handle any type and returns a type where all properties are either string[] or string: export type Quer ...

Setting the default checkbox selection in the Ng Multiselect dropdown (an Angular control)

Check out this sample code for creating a multiselect dropdown: <ng-multiselect-dropdown [placeholder]="'Select'" [data]="dropdownList" [(ngModel)]="selectedItems" [settings]="dropdownS ...

Accessing a variable within a function in Angular

Recently I started working with Angular and encountered an issue while trying to access a variable inside a function. Below is the code snippet that's causing me trouble: mergeImages() { var imgurl; var canvas: HTMLCanvasElement = this.canv ...