How do I get a ExtJS 4.1.X Bar Chart with a single bar to show that bar's label properly?
Asked Answered
B

5

27

If you try the live code example in the documentation at:

http://docs.sencha.com/ext-js/4-1/#!/api/Ext.chart.series.Bar

More than one label looks beautiful:

Bar Chart with Two Labels

data: [
    { 'name': 'metric one',  'data':5 },
    { 'name': 'metric two',  'data':27 }
]

However as soon as you reduce the dataset down to one label, the output looks horrible(notice the label for the bar appears half outside the top of the chart area, instead of vertically aligned with the bar it is to label):

Bar Chart with One Label

Is this a bug in ExtJS? How do I work around this? Exact ExtJS code that produces this output:

var store = Ext.create('Ext.data.JsonStore', {
    fields: ['name', 'data'],
    data: [
        { 'name': 'metric one',  'data':5 }
    ]
});

Ext.create('Ext.chart.Chart', {
    renderTo: Ext.getBody(),
    width: 500,
    height: 300,
    animate: true,
    store: store,
    axes: [{
        type: 'Numeric',
        position: 'bottom',
        fields: ['data'],
        label: {
            renderer: Ext.util.Format.numberRenderer('0,0')
        },
        title: 'Sample Values',
        grid: true,
        minimum: 0
    }, {
        type: 'Category',
        position: 'left',
        fields: ['name'],
        title: 'Sample Metrics'
    }],
    series: [{
        type: 'bar',
        axis: 'bottom',
        highlight: true,
        tips: {
          trackMouse: true,
          width: 140,
          height: 28,
          renderer: function(storeItem, item) {
            this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data') + ' views');
          }
        },
        label: {
            display: 'insideEnd',
            field: 'data',
            renderer: Ext.util.Format.numberRenderer('0'),
            orientation: 'horizontal',
            color: '#333',
            'text-anchor': 'middle'
        },
        xField: 'name',
        yField: 'data'
    }]
});
Blindage answered 27/11, 2012 at 14:59 Comment(0)
B
1

One solution is to replace

axisRange = to - from,

on line 383 of Axis.js in ExtJS with

axisRange = to - from == 0 ? 1 : to - from,

to prevent a divide by zero being assigned to the y coordinate of the axis label.

Blindage answered 29/11, 2012 at 13:34 Comment(0)
E
0

Yes, the default rendering does look weird when it is just one record.
It can be fixed or worked around though.

In concept, override the series renderer to fix the height and y point in case of single record -


renderer: function(sprite, record, attr, index, store) {
    if (store.getCount() == 1) {
        attr.height = 80;
        attr.y = 75;
    }
    return attr;
}

enter image description here

You can make changes to the actual overridden values (attr.height and attr.y) to suit your visual needs.

Here is your example modified to look close to what you would expect.


var store = Ext.create('Ext.data.JsonStore', {
    fields: ['name', 'data'],
    data: [
        {'name': 'metric one','data': 5}
        //,{'name': 'metric two','data': 7}
    ]
});


Ext.create('Ext.chart.Chart', {
    renderTo: Ext.getBody(),
    width: 500,
    height: 300,
    animate: true,
    store: store,
    axes: [{
        type: 'Numeric',
        position: 'bottom',
        fields: ['data'],
        label: {
            renderer: Ext.util.Format.numberRenderer('0,0')
        },
        title: 'Sample Values',
        grid: true,
        minimum: 0},
    {
        type: 'Category',
        position: 'left',
        fields: ['name'],
        title: 'Sample Metrics'}],
    series: [{
        type: 'bar',
        axis: 'bottom',

        highlight: true,
        tips: {
            trackMouse: true,
            width: 140,
            height: 28,
            renderer: function(storeItem, item) {
                this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data') + ' views');
            }
        },
        label: {
            display: 'insideEnd',
            field: 'data',
            renderer: Ext.util.Format.numberRenderer('0'),
            orientation: 'horizontal',
            color: '#333',
            'text-anchor': 'middle'
        },
        xField: 'name',
        yField: 'data',
        renderer: function(sprite, record, attr, index, store) {
            if (store.getCount() == 1) {
                attr.height = 80;
                attr.y = 75;
            }
            return attr;

        }}]
});​
Excellence answered 28/11, 2012 at 18:28 Comment(2)
You example moves the bar, not the label. The label is still off in heaven. It has given me hope though.Blindage
On closer inspection I can see that the y attribute is getting set to NaN on the text tag that wraps the label... is there a way to manually override the calculation that results in that?Blindage
S
0

If it seems right, just change the height to 150 from 300 :

Ext.create('Ext.chart.Chart', {
    renderTo: Ext.getBody(),
    width: 500,
    height: 150,
Scrutiny answered 7/2, 2013 at 16:38 Comment(0)
T
0

Updating to ExtJS 4.2 should fixes this.

Tunisia answered 11/4, 2013 at 15:7 Comment(0)
R
0

The problem is not in one bar, it is because of the range so if you have a wide range and one bar the labels will not repeat, it is great to hear that it is fixed in version 4.2 please confirm this if you try it.

Radiophotograph answered 23/5, 2013 at 18:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.