Need to draw a pie chart for your Angular application users? If so, then you're luck.

You can do it pretty easily with the aid of ngx-echarts.

And in this guide, I'll show you how to do it so you end up with a pretty chart that looks like this:

If you prefer to skip reading all these words, you can go straight to the source code on GitHub.

Otherwise, pull up a rock.

Not Starting From Scratch

In this article, I'll assume you already have ngx-echarts and its related dependencies installed and working. If not, feel free to visit my guide on getting started with ngx-echarts.

Then come back here.

Stock Options

Remember, when it comes to drawing charts with ngx-echarrts, all you need to do is include a bit of markup like this in your template:

<div echarts [options]="options"></div>

And define all your chart details in a property named options in the component class.

In other words, all the good stuff happens within that options object and not in the HTML.

So let's take a look at the related component class for drawing a pie chart.

Before we do that, though, let me explain what's going on in this application.

It's a CRM app. The code here is grabbing deals (opportunities to make money) by criteria. I'll explain the criteria in a moment.

You can see what the Deal type looks like here.

The point of the pie chart here is to show how much each contact is contributing to the user's overall sales pipeline. So contacts with higher deal values will show a larger pie slice than contacts with lower deal values.

With that in mind, take a look at the component class:

@Component({
  selector: 'app-deal-share-by-contact',
  templateUrl: './deal-share-by-contact.component.html',
  styleUrls: ['./deal-share-by-contact.component.css']
})
export class DealShareByContactComponent implements OnInit {

  options: any;
  pageTitle: string = 'Deal Share by Contact';
  chartData: any[] = [];

  constructor(private dealService: DealService) { }

  ngOnInit(): void {
    this.loadDeals();
  }

  private getDealCriteria(): DealCriteria {
    let criteria: DealCriteria = new DealCriteria();
    criteria.userId = "6014081e221e1b534a8aa432";
    
    return criteria;
  }

  private loadDeals() {
    let criteria: DealCriteria = this.getDealCriteria();

    console.log("Deal criteria is ", criteria);

    this.dealService.fetchDealsByCriteria(criteria).subscribe(
      (deals: Deal[]) => this.handleDealsResponse(deals),
      (err: Error) => this.handleError(err)
    );
  }

  private handleDealsResponse(deals: Deal[]) {
    deals.forEach(deal => {
      this.addDeal(deal);
    });

    console.log("chartData is ",this.chartData);

    this.setOptions();
  }

  private addDeal(deal: Deal) {
    let value: number = this.dealService.getAmount(deal);
    let contactName: string = deal.contact.firstName + ' ' + deal.contact.lastName;

    let dataPoint: any = this.chartData.find(dp => dp.name === contactName);

    if (dataPoint) {
      let amount = this.dealService.getAmount(deal);
      dataPoint.value = value + amount;
    } else {
      dataPoint = {};
      dataPoint.value = value;
      dataPoint.name = contactName;

      this.chartData.push(dataPoint);
    }
  }

  private setOptions() {
    this.options = {
      tooltip: {
        trigger: 'item'
      },
      series: [
        {
          type: 'pie',
          radius: '60%',
          data: this.chartData,
          emphasis: {
            itemStyle: {
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowColor: 'rgba(0, 0, 0, 0.5)'
            }
          }
        }
      ]
    };
  }

  private handleError(err: Error) {
    console.error(err);
  }
}

As I did previously, I'll cover each of those methods individually.

The ngOnInit() method just calls loadDeals() to load deals by criteria from the back-end REST service.

What are the criteria? They're specified in a class appropriately named DealCriteria. The setDealCriteria() method instantiates that class and sets the only criteria needed here: the user ID.

That ID is hardcoded just to keep things simple. Normally, it's cached in a service.

The loadDeals() method subscribes to the Observable returned from DealService and grabs the array of Deal objects emitted by it before handing off execution to handleDealsResponse().

In handleDealsResponse(), the code streps through each Deal object in the array and invokes the addDeal() method. 

The addDeal() method grabs the necessary data from the Deal object and extracts only the info needed to draw the pie chart.

First, it gets the deal value. That's the monetary value of the deal.

Then, it get's the name of the contact associated with the deal.

It uses those two values to create an any object called dataPoint.

However, a contact may have more than one deal. So the if check you see in addDeal() checks to see if the contact already has deal in the chartData array. 

If the contact already has a deal, then the value of the current deal is added to contact's existing deal value in the array.

Otherwise, the code creates a new any object (called dataPoint) and sets the name and value properties accordingly.

Finally, that dataPoint object gets added to the chartData array. That's the array that gets included in the options object.

Speaking of that options object, take a look at the setOptions() method:

private setOptions() {
  this.options = {
    tooltip: {
      trigger: 'item'
    },
    series: [
      {
        type: 'pie',
        radius: '60%',
        data: this.chartData,
        emphasis: {
          itemStyle: {
            shadowBlur: 10,
            shadowOffsetX: 0,
            shadowColor: 'rgba(0, 0, 0, 0.5)'
          }
        }
      }
    ]
  };
}

The tooltip property shows details about each pie slice when the user hovers over it. That trigger: 'item' part you see means that the tooltip is mainly reserved for pie charts because they don't have a category axis.

The series object specifies details about the chart.

The type property is fairly self-explanatory. It's set to 'pie' here because this is a pie chart.

That width property specifies the size of the pie chart relative to the enclosing element. It's set to 60% here but your mileage may vary.

The data property lives up to its name. That's where the pie chart data gets specified.

It's an array of objects that must include both a name and a value property. As you saw above, the name property specifies the name of the contact and the value property specifies the value of all deals associated with the contact.

So the data for the pie chart you saw in the intro looks like this:

[
   {
      "value":60000,
      "name":"Opus Mei"
   },
   {
      "value":50000,
      "name":"Blinky Scene"
   },
   {
      "value":600000,
      "name":"Governor Rover"
   },
   {
      "value":20000,
      "name":"Yeezu Joy"
   },
   {
      "value":400000,
      "name":"Mercy Windsor"
   },
   {
      "value":400000,
      "name":"Lucy Cheng"
   },
   {
      "value":200000,
      "name":"Frum Lezilia"
   }
]

Finally, that emphasis object just sets styling detail. 

Wrapping It Up

And that's all there is to it. 

Since you certainly don't need a pie chart that looks exactly like the one I showed above, you'll need to update the code to suit your own requirements.

However, you now know how to get the ball rolling.

Now it's time to start rolling it and have fun!

Photo by William Fortunato from Pexels