[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: DataLabels Custom

Hello Kamil,
I have 2 more questions.
- When we have the icon it's not possible to present a label also, right?
- I adjust the position of the icon with CSS to present in the place where we can see the tasks joining but in some cases doesn't work well. Do you you think you can help me on that?

What I did:

Code: Select all

format: '<div style="margin-left: -30px; margin-top: -10px;"><img src=' + $parameters.IconOverlapingPath + '></div>',
Example working well: https://personal-ieehgzmp.outsystemsclo ... lektroApp/
Examaple doesn't work well: https://ptorres.outsystemscloud.com/Gan ... sDemo/Home

Thanks in advance, Paulo Torres
kamil.k
Posts: 458
Joined: Thu Oct 06, 2022 12:49 pm

Re: DataLabels Custom

Hello There,

Thanks for coming back with your questions!

Answering your first question, you can easily add any HTML element to the current structure apart from the img tag. Please refer to the updated demo where I added a barName property as a label next to the image and a minor positioning change (your second question) that covers data from both examples you provided: https://jsfiddle.net/BlackLabel/bqo4xpsh/.

Let me know how this works for you,
Rgards!
Kamil Kubik
Highcharts Developer
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: DataLabels Custom

Hi Kamil,
Can you help me to fix this code?

Code: Select all

format: '<div style="margin-left: ' + $parameters.MarginLeft + 'px; margin-top: ' + $parameters.MarginTop + 'px;"><img src=' + $parameters.IconOverlapingPath + '> <span style="position: relative; top: -10px">${point.barName}</span></div>',
The $ is presented in the label.

Thanks, Paulo Torres
kamil.k
Posts: 458
Joined: Thu Oct 06, 2022 12:49 pm

Re: DataLabels Custom

Hello,

As I can see, you use the template literals pattern but without the backticks, so the ${point.barName} shows as a string and the $ is visible. Please refer to this code instead:

Code: Select all

format: '<div style="margin-left: ' + $parameters.MarginLeft + 'px; margin-top: ' + $parameters.MarginTop + 'px;"><img src=' + $parameters.IconOverlapingPath + '> <span style="position: relative; top: -10px">' + point.barName + '</span></div>',

Regards!
Kamil Kubik
Highcharts Developer
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: DataLabels Custom

Hi kamil,
Thanks a lot, works like a charm. The only issue it«s because the font size and color of the text is not the same but this is not a big issue for me.

Paulo Torres
kamil.k
Posts: 458
Joined: Thu Oct 06, 2022 12:49 pm

Re: DataLabels Custom

I'm glad it works for you!

According to the text color and font size, have you tried adding the CSS inline styles?

Regards!
Kamil Kubik
Highcharts Developer
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: DataLabels Custom

Hi Kamil,
I found an issue with this feature you helped me to do.

When I have two bars in the same line there is no label or percentage of the task. See where on QA Database Migration line: https://ptorres.outsystemscloud.com/Gan ... sDemo/Home

Thanks in advance for your support.

Paulo Torres
jakub.j
Posts: 1084
Joined: Tue Jan 24, 2023 11:14 am

Re: DataLabels Custom

Hey!

When I simplified your chart, I found out that the dataLabels where disabled in series config for the whole series, you need to remove that, see:

Demo: https://jsfiddle.net/BlackLabel/su5jrwyd/

I hope you find it useful
Kind regards
Jakub
Jakub
Highcharts Developer
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: DataLabels Custom

Hi jakub,
Thanks for your help again :)

I switch the dataLabels for true and when I have label it appears but in the another bar in the same line doesn't appears the progress (Completed). With my JS it's possible to make this working or it's better to make a change to have a structure DataLabels in each bar like you did?

See here: https://ptorres.outsystemscloud.com/Gan ... sDemo/Home

My code:

Code: Select all

var today = new Date(),
    day = 1000 * 60 * 60 * 24,

    // Dynamic Variables for Tooltip
    tooltipStartText = $parameters.TooltipStartText,
    tooltipEndText = $parameters.TooltipEndText,
    tooltipCompletedText = $parameters.TooltipCompletedText,
    tooltipOwnerText = $parameters.TooltipOwnerText,
    tooltipProjectManagerText = $parameters.TooltipProjectManagerText,
    iconOverlapingPath = $parameters.IconOverlapingPath,

    // Utility functions
    dateFormat = Highcharts.dateFormat,
    defined = Highcharts.defined,
    isObject = Highcharts.isObject;

// Set to 00:00:00:000 today
today.setUTCHours(0);
today.setUTCMinutes(0);
today.setUTCSeconds(0);
today.setUTCMilliseconds(0);


// THE CHART
Highcharts.ganttChart($parameters.ChartContainerId, {

 chart: {
    backgroundColor: $parameters.BackgroundColor,
        style: {
            fontFamily: $parameters.Font,
            //stroke: 'black',
        },
        
    events: {
      load: function() {
        const chart = this;

        chart.series.forEach((series) => {
          series.points.forEach((point) => {
            const y = point.y,
              id = point.id,
              filteredSeriesPoints = series.points.filter(({
                id
              }) => id !== point.id);

            chart.series.forEach((insideSeries) => {
              series.points.forEach((insidePoint) => {
                if (filteredSeriesPoints.some((filteredPoint) => filteredPoint.y === y)) {
                  if (
                    insidePoint.y === point.y &&
                    point.x < insidePoint.x2 &&
                    point.x2 > insidePoint.x2 &&
                    insidePoint.index < point.index
                  ) {
                    point.update({
                      dataLabels: {
                        enabled: $parameters.HasIconOverlapingTasks,
                        useHTML: true,
                        align: "left",
                        x: -20,
                        format: '<div style="margin-left: ' + $parameters.MarginLeft + 'px; margin-top: ' + $parameters.MarginTop + 'px;"><img src=' + $parameters.IconOverlapingPath + '> <span style="position: relative; top: -10px; margin-left: 10px;">' + point.barName + '</span></div>',
                      },
                    }, false, false);
                  }

                  if (
                    insidePoint.y === point.y &&
                    point.x2 > insidePoint.x &&
                    point.x2 < insidePoint.x2 &&
                    insidePoint.index < point.index
                  ) {
                    point.update({
                      dataLabels: {
                        enabled: $parameters.HasIconOverlapingTasks,
                        useHTML: true,
                        align: "right",
                        x: 20,
                        format: '<div style="margin-left: ' + $parameters.MarginLeft + 'px; margin-top: ' + $parameters.MarginTop + 'px;"><img src=' + $parameters.IconOverlapingPath + '> <span style="position: relative; top: -10px; margin-left: 10px;">' + point.barName + '</span></div>',
                      },
                    }, false, false);
                  }
                } else {
                  point.update({
                    dataLabels: {
                      enabled: $parameters.IsShowNameOnBar,
                      format: point.barName || (!isNaN(point.options.completed) ? point.options.completed * 100 + '%' : '')
                    },
                  }, false, false);
                }
              });
            });
          });
        });
        
        chart.redraw();
      },
    }
  },

    title: {
        text: $parameters.Title
    },
    subtitle: {
        text: $parameters.SubTitle
    },
    navigator: {
        enabled: $parameters.HasNavigator,
        liveRedraw: true,
        series: {
            type: 'gantt',
            pointPlacement: 0.5,
            pointPadding: 0.25,
            accessibility: {
                enabled: true
            }
        },
    },
    scrollbar: {
        enabled: $parameters.HasScrollbar
    },
    rangeSelector: {
        enabled: $parameters.HasRangeSelector
    },
    //Remove logo/credits Highcharts
    credits: {
        enabled: false
    },

    yAxis: {
        type: 'treegrid',
        uniqueNames: $parameters.IsUniqueNames
    },

    //Customization of tooltip
    tooltip: {
        pointFormatter: function() {
            var point = this,
                format = '%e. %b',
                options = point.options,
                completed = options.completed,
                amount = isObject(completed) ? completed.amount : completed,
                status = ((amount || 0) * 100) + '%',
                lines;

            lines = [{
                value: point.name,
                style: 'font-weight: bold;'
            }, {
                title: tooltipStartText,
                value: dateFormat(format, point.start)
            }, {
                visible: !options.milestone,
                title: tooltipEndText,
                value: dateFormat(format, point.end)
            }, {
                title: tooltipCompletedText,
                value: status
            }, {
                visible: options.isShowOwner,
                title: tooltipOwnerText,
                value: options.owner || 'unassigned'
            }, {
                visible: options.isProjectManager,
                title: tooltipProjectManagerText,
                value: options.projectManager || 'unassigned'
            }];


            return lines.reduce(function(str, line) {
                var s = '',
                    style = (
                        defined(line.style) ? line.style : 'font-size: 0.8em;'
                    );
                if (line.visible !== false) {
                    s = (
                        '<span style="' + style + '">' +
                        (defined(line.title) ? line.title + ': ' : '') +
                        (defined(line.value) ? line.value : '') +
                        '</span><br/>'
                    );
                }
                return str + s;
            }, '');
        }
    },

    xAxis: [{ // first x-axis
        currentDateIndicator: $parameters.IsCurrDateIndicator,
        min: $parameters.StartDate.getTime(),
        max: $parameters.EndDate.getTime() + ($parameters.EndDateMarginDays * day),
        tickInterval: 1000 * 60 * 60 * 24 // 1 month
    }, { // second x-axis
        tickInterval: 1000 * 60 * 60 * 24 * 7 // 1 week
    }, { // third x-axis
        tickInterval: 1000 * 60 * 60 * 24 * 30, // 1 day
    }],


    accessibility: {
        keyboardNavigation: {
            seriesNavigation: {
                mode: 'serialize'
            }
        },

        point: {
            descriptionFormatter: function(point) {
                var completedValue = point.completed ?
                    point.completed.amount || point.completed : null,
                    completed = completedValue ?
                    ' Task ' + Math.round(completedValue * 1000) / 10 + '% completed.' :
                    '',
                    dependency = point.dependency &&
                    point.series.chart.get(point.dependency).name,
                    dependsOn = dependency ? ' Depends on ' + dependency + '.' : '';

                return Highcharts.format(
                    point.milestone ?
                    '{point.yCategory}. Milestone at {point.x:%Y-%m-%d}. Owner: {point.owner}.{dependsOn}' :
                    '{point.yCategory}.{completed} Start {point.x:%Y-%m-%d}, end {point.x2:%Y-%m-%d}. Owner: {point.owner}.{dependsOn}', {
                        point,
                        completed,
                        dependsOn
                    }
                );
            }
        }
    },



    plotOptions: {
        series: {
            cursor: 'pointer',
            allowPointSelect: $parameters.IsAllowPointSelect,
            dragDrop: {
                draggableX: $parameters.IsDraggableX,
                dragPrecisionX: day / 3 // Snap to eight hours
            },
            point: {
                events: {
                    // Function for click on bar, will return the ID of element
                    click: function() {
                        $actions.OnClickElement(this.aux_id, this.aux_type);
                    },

                    drop: function(e) {
                        $actions.OnDragDropElement(this.aux_id, this.aux_type, this.start, this.end);
                    }
                }
            }
        },

        gantt: {
            dataLabels: {
                formatter: function() {
                    const point = this.point,
                        barName = point.barName;

                    if (barName !== '') {
                        return barName;
                    } else {
                        return point.options.completed.amount * 100 + '%';
                    }
                }
            }
        },

        lang: {
            accessibility: {
                axis: {
                    xAxisDescriptionPlural: 'The chart has a two-part X axis showing time in both week numbers and days.',
                    yAxisDescriptionPlural: 'The chart has one Y axis showing task categories.'
                }
            }
        },
    },

    //Json with elements of Gantt
  series: [{
    name: $parameters.ProjectName,
    data: JSON.parse($parameters.JSONData),

    dataLabels: {
        enabled: true,
        //format: '<div style="margin-left: -30px; margin-top: -10px;"><img src="/GanttHighcharts/img/GanttHighcharts.warning.png"></div>',
        //format: '<div style="margin-left: ' + $parameters.MarginLeft + 'px; margin-top: ' + $parameters.MarginTop + 'px;"><img src=' + $parameters.IconOverlapingPath + '></div>',
    }
  }],
  isGantt: true

});

Thanks in advance, Paulo Torres
jakub.j
Posts: 1084
Joined: Tue Jan 24, 2023 11:14 am

Re: DataLabels Custom

Hey!

You had a wrong condition in gantt.dataLabels.formatter, see:

Demo: https://jsfiddle.net/BlackLabel/om8b9t5p/

I hope you will find it useful
Kind regards
Jakub
Jakub
Highcharts Developer
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: DataLabels Custom

Hi Jakub,
I think you change for this:

Code: Select all

if (barName && barName.length) {
Right?

But instead to have the percentage of the progress it shows NaN%. Do you understand why?

Thanks, Paulo Torres
jakub.j
Posts: 1084
Joined: Tue Jan 24, 2023 11:14 am

Re: DataLabels Custom

Hey,

It's because the value point.options.completed.amount was undefined, you need to display point.completed, see:

Demo: https://jsfiddle.net/BlackLabel/eby2a5ow/

I hope you find it useful
Kind regards
Jakub
Jakub
Highcharts Developer
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: DataLabels Custom

jakub.j wrote: Fri Feb 09, 2024 7:52 am Hey,

It's because the value point.options.completed.amount was undefined, you need to display point.completed, see:

Demo: https://jsfiddle.net/BlackLabel/eby2a5ow/

I hope you find it useful
Kind regards
Jakub
You are right, I had the incorrect place where I get the completed. Now this works like a charm :D

Thanks a lot, you are always amazing :)

Return to “Highcharts Gantt”