2

I am using the chart js to display a bar graph. It's working correctly on normal instances, but I am willing to change the color or a small portion of the label i.e, I want to include some HTML on the label of the bar chart. But, it isn't rendering the HTML instead it is showing plain HTML text.

If it is not possible, it's okay for me if there is another way to achieve this like, change the color of the price and keep the name as it is.

let $js_dom_array = ["43.28", "93.13"];
let $js_am_label_arr = ["<span>$0</span> None", "<span class='text-danger'>$23.63</span> Handicap Accessible"];

let ctx2 = document.getElementById("barChart").getContext("2d");

        let chart = new Chart(ctx2, {
            type: 'bar',
            data: {
                labels: $js_am_label_arr,
                datasets: [{
                    label: 'Amenity Name',
                    data: $js_dom_array,
                    backgroundColor: 'rgba(26,179,148,0.5)',
                    borderColor: 'rgba(75, 192, 192, 1)',
                    borderWidth: 1
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: true,
                legendCallback: function(chart) {
                    var text = [];
                    for (var i=0; i<chart.data.datasets.length; i++) {
                        console.log(chart.data.datasets[i]); // see what's inside the obj.
                        text.push(chart.data.datasets[i].label);
                    }
                    return text.join("");
                },
                tooltips: {
                    "enabled": false
                },
                scales: {
                    xAxes: [{
                        stacked: false,
                        beginAtZero: true,
                        ticks: {
                            stepSize: 1,
                            min: 0,
                            autoSkip: false,
                            callback: function(label, index, labels) {
                                if (/\s/.test(label)) {
                                    return label.split(" ");
                                }else{
                                    return label;
                                }
                            }
                        }
                    }]
                },
                animation: {
                    duration: 0,
                    onProgress: function() {
                        var chartInstance = this.chart,
                            ctx = chartInstance.ctx;
                        ctx.font = Chart.helpers.fontString(16, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
                        ctx.textAlign = 'center';
                        ctx.textBaseline = 'bottom';
                        this.data.datasets.forEach(function(dataset, i) {
                            var meta = chartInstance.controller.getDatasetMeta(i);
                            meta.data.forEach(function(bar, index) {
                                if (dataset.data[index] > 0) {
                                    let data = dataset.data[index];
                                    ctx.fillText('$'+Math.round(data), bar._model.x, bar._model.y - 5);
                                }
                            });
                        });
                    }
                },
            }
        });
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
    <canvas id="barChart" height="140"></canvas>
</div>

#Note: Here, you might see that the data in $js_am_label_arr is already an HTML element, but if there is something from where I could pass the array of the raw values and the convert in HTML than I could pass the raw value (without) as well. Currently $js_am_label_arr is created as:

if($avg_amount < 0){
    $text_color = 'text-danger';
    $avg_amount_text = "<span class='text-danger'>$".abs($avg_amount)."</span>";
}else{
    $text_color = '';
    $avg_amount_text = "<span>$".abs($avg_amount)."</span>";
}
$am_label_arr[] = $avg_amount_text.' '.$fv['amenity_name'];

Update:

Expected Output

So if the value is negative for example in the above case, its -$23.63. In this case, I want the label to be ($23.63)[in color red] followed by the name Handicap Accessible. This can be seen at the result as well, text-danger classes is added to show that part in red color.

enter image description here

Saroj Shrestha
  • 2,696
  • 4
  • 21
  • 45
  • [this question can help you](https://stackoverflow.com/questions/23631170/html-in-chart-js-labels): HTML in Chart.js labels – gaetanoM Aug 15 '20 at 14:09
  • Does this answer your question? [HTML in Chart.js labels](https://stackoverflow.com/questions/23631170/html-in-chart-js-labels) – Vinay Aug 15 '20 at 15:29
  • @Viney no. instead, more than that https://stackoverflow.com/questions/37005297/custom-legend-with-chartjs-v2-0 this looks close but i am not being able to work in my case. – Saroj Shrestha Aug 15 '20 at 15:32
  • I see, have a look over [here](https://www.chartjs.org/docs/latest/configuration/legend.html#html-legends) – Vinay Aug 15 '20 at 15:40
  • @viney I have already read those documents, could you provide a working jsfiddle link by pointing out what I am missing? I have already tried with that legendCallback – Saroj Shrestha Aug 15 '20 at 15:41
  • What is excepted output ? is it ok if you don't show it as label but legends ? – Swati Aug 18 '20 at 17:01
  • @Swati I have updated the question you can see the output while running the above code, there it shows `` I just want that part to be red in color. – Saroj Shrestha Aug 19 '20 at 08:30
  • I updated my answer, check and move your mouse pointer over the chart bars, only one is red – João Pimentel Ferreira Aug 20 '20 at 15:12

3 Answers3

0

As far as i know, its not possible to do what you want. With the current version (v2.9.3) its not even possible to change the color for specifics X ticks labels, you can only change the color for every label with:

    options: {
            scales: {
                yAxes: [{
                    ticks: {
                        fontColor: "red",
                    }
                }],
                xAxes: [{
                    ticks: {
                        fontColor: "red",
                    }
                }]
            }
        }

There is a workaround with version v2.6.0 (as you tagged this version, i imagine you are using it) wich you can pass an array of colors to fontColor, like: fontColor: ["red","green"], but you need to change some code lines of chartjs and yet you cannot change just a specific part of the text of axis tick label as you want.

If you have interested in this solution, you can check it here Add possibility to change style for each of the ticks

But again, this solution is related to an older version of chartjs and i dont know what features you lose here.

Looks like it will be able to change the color for each ticks in version 3.0, but this version isnt released yet.

UPDATED

I done a simple example here with c3/d3 js. but it has some points:

  1. It take a little time to show Labels updated when chart is rendered.
  2. On changeTickLabel i did a harded code to check value and then append the text (like 'Handicap Accessible'). So here you will need to find logic that is better to you.

var chart = c3.generate({
    onrendered: function () { changeTickLabel() },
    data: {
        columns: [
            ['data1', 43.28, 93.13]
        ],
        type: 'bar',
    },
    axis: {
        x : {
           type: 'category',
           categories:  ["$0", "$23.63"],
           tick: {
                multiline:false,
                culling: {
                    max: 1
                },
            },
        },
    }
});



function changeTickLabel(){

d3.selectAll('.c3-axis-x .tick tspan')
  .each(function(d,i){
    var self = d3.select(this);
    var textValue = self.text();  

    if(textValue !== '$0'){
      self.style("fill", "red");
    self.append('tspan').style("fill", "black").text(' Handicap Accessible');  
    }
    else {
      self.append('tspan').text(' None');
    }  
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.20/c3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="chart"></div>
Luis Paulo Pinto
  • 5,578
  • 4
  • 21
  • 35
0

You can change the color when you hover the label, with the tooltips callback

Move your mouse over the bar

let $js_dom_array = [43.28, 93.13];
  let $js_am_label_arr = ["$0", "$23.63"];

  let ctx2 = document.getElementById("barChart").getContext("2d");

  let chart = new Chart(ctx2, {
      type: 'bar',
      data: {
          labels: $js_am_label_arr,
          datasets: [{
              backgroundColor: 'rgba(26,179,148,0.5)',
              label: 'Amenity Name',
              data: $js_dom_array,
          }]
      },
      options: {
          responsive: true,
          maintainAspectRatio: true,
          tooltips: {
              enable: true,
              callbacks: {
                  labelTextColor: function(tooltipItem, chart) {
                  if(tooltipItem.index === 1)
                      return 'red';
                  }
              }
          },
          scales: {
              xAxes: [{
                  stacked: false,
                  beginAtZero: true,
                  ticks: {
                      stepSize: 1,
                      min: 0,
                      autoSkip: false,
                      fontColor: "red",
                      callback: function(label, index, labels) {
                          if (/\s/.test(label)) {
                              return label.split(" ");
                          }else{
                              return label;
                          }
                      }
                  }
              }]
          }
      }
  });
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
    <canvas id="barChart" height="140"></canvas>
</div>
João Pimentel Ferreira
  • 14,289
  • 10
  • 80
  • 109
  • This is not the answer, I was looking at something like https://ibb.co/vcJhFQY amount in red color and remaining string in black. Also, I am open to any other plugin if this feature is unachievable with this plugin. – Saroj Shrestha Aug 20 '20 at 15:17
  • @SarojShrestha I edited the answer, check now. You can change the text of the labels according to index, but you cannot change the color of it according to the index. You can just change the color to all of them. – João Pimentel Ferreira Aug 20 '20 at 19:15
0

As you are open to any plugin so i suggest you to use HighCharts to achieve above case . In below demo code i have just passed the label value to categories in xAxis and done a little change to span tag . i.e : i have added inline css to span where you need to display color red .

Here is demo code :

var chart;
let $js_dom_array = [43.28, 93.13];
let $js_am_label_arr = ["<span>$0</span> None", "<span style='color:red'>$23.63</span> Handicap Accessible"];
$(document).ready(function() {
  chart = new Highcharts.Chart({
    chart: {
      renderTo: 'chart_container', //under chart_container chart will display
      defaultSeriesType: 'bar', //bar grapgh
      backgroundColor: '#CCCCCC',
      type: 'column' //to display in columns wise
    },
    plotOptions: {
      bar: {
        colorByPoint: true,
        dataLabels: {
          enabled: false
        }
      }
    },
    title: {
      text: 'Something.... '
    },
    xAxis: {
      categories: $js_am_label_arr, //for value in labels
    },
    series: [{
      name: 'Amenity Name',
      data: $js_dom_array //array value to plot data
    }]

  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/gantt/highcharts-gantt.js"></script>

<div id="chart_container"></div>
Swati
  • 28,069
  • 4
  • 21
  • 41