0

Can anybody tell me how to give a different field for a label and legend in pie chart in extjs? I have a store with two fields with name,value. I want to display name field in legend and value field in label. Now I am getting the same value for both labe1 and legend.

Thanks

Illidanek
  • 996
  • 1
  • 18
  • 32
mohan
  • 13,035
  • 29
  • 108
  • 178

4 Answers4

2

Configure the label property of your pie serie like this:

label: {
    // name of the model field to use as legend
    field: 'name'
    ,renderer: function(value, label, storeItem) {
        // storeItem is your model, so return the value you want as label
        return storeItem.get('value');
    }
}

Edit:

The previous code only works from since Ext 4.2. To use it with 4.1, you'd have to override Ext.chart.series.Pie#onPlaceLabel() method to replace the lines:

    label.setAttributes({
        text: format(storeItem.get(field[index]))
    }, true);

With these, from Ext4.2 code:

    label.setAttributes({
        text: format(storeItem.get(field), label, storeItem, item, i, display, animate, index)
    }, true);

Edit 2: How to override for Ext 4.1

The syntax for overriding a class in Ext 4 is the same as the one for extending, except that you use override instead of extend. The override class is named, like any other class. In order for the override to be loaded, you have to require it, exactly like a normal class (if you don't use Ext Loader, then you must include the file in a script tag.

Now, here's the code that will make the value renderer works in the same way as Ext4.2:

// Again, you're free to chose the class name, just ensure the Loader can find the file
// (and don't forget to require it!)
Ext.define('MyApp.Ext.char.series.Pie', {
    override: 'Ext.chart.series.Pie'

    ,onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
        var me = this,
            chart = me.chart,
            resizing = chart.resizing,
            config = me.label,
            format = config.renderer,
            field = [].concat(config.field),
            centerX = me.centerX,
            centerY = me.centerY,
            middle = item.middle,
            opt = {
                x: middle.x,
                y: middle.y
            },
            x = middle.x - centerX,
            y = middle.y - centerY,
            from = {},
            rho = 1,
            theta = Math.atan2(y, x || 1),
            dg = theta * 180 / Math.PI,
            prevDg;

        opt.hidden = false;

        if (this.__excludes && this.__excludes[i]) {
            opt.hidden = true;
        }

        function fixAngle(a) {
            if (a < 0) {
                a += 360;
            }
            return a % 360;
        }

        label.setAttributes({
            // Removed:
            // text: format(storeItem.get(field[index]))
            // Added:
            text: format(storeItem.get(config.field), label, storeItem, item, i, display, animate, index)
        }, true);

        switch (display) {
            case 'outside':
                rho = Math.sqrt(x * x + y * y) * 2;
                //update positions
                opt.x = rho * Math.cos(theta) + centerX;
                opt.y = rho * Math.sin(theta) + centerY;
                break;

            case 'rotate':
                dg = fixAngle(dg);
                dg = (dg > 90 && dg < 270) ? dg + 180: dg;

                prevDg = label.attr.rotation.degrees;
                if (prevDg != null && Math.abs(prevDg - dg) > 180 * 0.5) {
                    if (dg > prevDg) {
                        dg -= 360;
                    } else {
                        dg += 360;
                    }
                    dg = dg % 360;
                } else {
                    dg = fixAngle(dg);
                }
                //update rotation angle
                opt.rotate = {
                    degrees: dg,
                    x: opt.x,
                    y: opt.y
                };
                break;

            default:
                break;
        }
        //ensure the object has zero translation
        opt.translate = {
            x: 0, y: 0
        };
        if (animate && !resizing && (display != 'rotate' || prevDg != null)) {
            me.onAnimate(label, {
                to: opt
            });
        } else {
            label.setAttributes(opt, true);
        }
        label._from = from;
    }
});

As you can see, I had to copy-paste the whole method code. I don't like that because that makes us largely exposed to any code change in future version, however there is no other possible way to change the bit of code I'm targeting.

In real life, in order to safeguard against this risk, I would add a version check and issue a warning if Ext version is greater than 4.1:

// Using a function instead of a raw object, in order to run some code at the time of class definition
Ext.define('MyApp.Ext.char.series.Pie', function() {
    if (Ext.getVersion().isGreaterThanOrEqual('4.2')) {
        Ext.Logger.warn('This override is rendered useless since Ext4.2');
        return {};
    } else {
        return {
            override: 'Ext.chart.series.Pie'

            ,onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
                var me = this,
                    chart = me.chart,
                    resizing = chart.resizing,
                    config = me.label,
                    format = config.renderer,
                    field = [].concat(config.field),
                    centerX = me.centerX,
                    centerY = me.centerY,
                    middle = item.middle,
                    opt = {
                        x: middle.x,
                        y: middle.y
                    },
                    x = middle.x - centerX,
                    y = middle.y - centerY,
                    from = {},
                    rho = 1,
                    theta = Math.atan2(y, x || 1),
                    dg = theta * 180 / Math.PI,
                    prevDg;

                opt.hidden = false;

                if (this.__excludes && this.__excludes[i]) {
                    opt.hidden = true;
                }

                function fixAngle(a) {
                    if (a < 0) {
                        a += 360;
                    }
                    return a % 360;
                }

                label.setAttributes({
                    // Removed:
                    // text: format(storeItem.get(field[index]))
                    // Added:
                    text: format(storeItem.get(config.field), label, storeItem, item, i, display, animate, index)
                }, true);

                switch (display) {
                    case 'outside':
                        rho = Math.sqrt(x * x + y * y) * 2;
                        //update positions
                        opt.x = rho * Math.cos(theta) + centerX;
                        opt.y = rho * Math.sin(theta) + centerY;
                        break;

                    case 'rotate':
                        dg = fixAngle(dg);
                        dg = (dg > 90 && dg < 270) ? dg + 180: dg;

                        prevDg = label.attr.rotation.degrees;
                        if (prevDg != null && Math.abs(prevDg - dg) > 180 * 0.5) {
                            if (dg > prevDg) {
                                dg -= 360;
                            } else {
                                dg += 360;
                            }
                            dg = dg % 360;
                        } else {
                            dg = fixAngle(dg);
                        }
                        //update rotation angle
                        opt.rotate = {
                            degrees: dg,
                            x: opt.x,
                            y: opt.y
                        };
                        break;

                    default:
                        break;
                }
                //ensure the object has zero translation
                opt.translate = {
                    x: 0, y: 0
                };
                if (animate && !resizing && (display != 'rotate' || prevDg != null)) {
                    me.onAnimate(label, {
                        to: opt
                    });
                } else {
                    label.setAttributes(opt, true);
                }
                label._from = from;
            }
        };
    }
}()); // the define function must be executed manually with overrides (this is documented in the API)
rixo
  • 23,815
  • 4
  • 63
  • 68
  • thanks for your answer return storeItem.get('value'); this line am gettign error Cannot call method 'get' of undefined – mohan May 31 '13 at 11:57
  • What version of Ext4 are you using precisely? – rixo May 31 '13 at 12:38
  • See my updated answer. You'll have to either upgrade to 4.2 or override `Ext.chart.series.Pie` :-/ – rixo May 31 '13 at 16:00
  • can you briefly tell how to overide Ext.chart.series.Pie .In which file need to change? – mohan May 31 '13 at 16:08
  • I've added the code for a clean override. You should absolutely never directly edit library files. – rixo Jun 01 '13 at 11:07
  • thanks rixo this is working .i place the onPlaceLabel method directly in that series whether that will create any problem? – mohan Jun 03 '13 at 05:13
  • That should be fine. Is that because you're not using Ext.Loader? If you're working with a single file, you can paste my code before the `Ext.onReady()` call too. – rixo Jun 03 '13 at 07:32
  • can u help in this question http://stackoverflow.com/questions/16891460/how-to-show-label-with-line-and-display-label-outside-in-piechart-in-extjs – mohan Jun 03 '13 at 08:38
1
I don't know whether it is against the copyright law or not 

and i am not responsible anything you do. but it will work

step 1 

open  touch/src/chart/series/pie.js file 

step 2
 add one property to this file  (like legendLabel:null,)
step 3 
 Edit method  provideLegendInfo: function (target) . and change 
 labelField = this.getLabelField(), to
 labelField = this.getLegendLabel()
step 4<br>
Add new property to series you create in your file to show pie chart


    series: [
                    {
                        type: 'pie',
                        legendLabel :'name',
                        xField: 'value',                        
                        labelField: 'value',

}]


promote  this answer if you find this is helpful 
thank u
Risto
  • 11
  • 2
1

this should works for Ext 4.0

new Ext.chart.Chart({
  store: store, 
  series: [{
    type: 'pie',
    field: 'value',
    label: {
        field: 'name',
        renderer: function(value){
            Ext.each(store.data.items, function(item){
                if(item.data.name == value) {
                    value = item.data.value;
                }
            });
            return value;
        }
    }
  }],
  ... 

store data looks like:

[{"name":"series1","value":5},{"name":"series2","value":7}]
Konrad Rozner
  • 81
  • 2
  • 4
0

I have a way to show two different labels on legend and PIE separately using rendererFn (sprites). Here you don't need to edit the JS files.

In the "series" section, Under the Label category, use the "field" to display the LEGEND text and in the renderer function use values as output to return the values on to the pie.

series: [{ type: 'pie', field: 'value', donut: 25,
showInLegend: true,

        label: {
            field: 'name',
            renderer: {rendererFn},
            display: 'inside'
        }
        ,renderer: function(sprite, config, rendererData, index) {
            return { text: {rendererFn}(window.dataJSON[index]['value']) };
        }
}]

This would suffice.

MafazR
  • 41
  • 3