最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - dynamically changing chart series extjs 4 - Stack Overflow

programmeradmin3浏览0评论

I'm using Extjs 4 with the MVC architecture.

I have a python script that outputs this Json Data :

{
"data": [
    {
        "inAnalysis": 3, 
        "inQuest": 2, 
        "inDevelopment": 6, 
        "total": 12, 
        "inValidation": 1, 
        "Month": 1303
    }, 
    {
        "inAnalysis": 1, 
        "total": 5, 
        "Month": 1304, 
        "inDevelopment": 4
    }
], 
"success": true, 
"metaData": {
    "fields": [
        {
            "name": "inAnalysis"
        }, 
        {
            "name": "inQuest"
        }, 
        {
            "name": "inDevelopment"
        }, 
        {
            "name": "inValidation"
        }, 
        {
            "name": "isDuplicate"
        }, 
        {
            "name": "New"
        }, 
        {
            "name": "total"
        }
    ], 
    "root": "data"
}

}

I want the fields of my MetaData to be used as the chart series, so I have a store like this :

Ext.define('Proj.store.ChartData', {
extend: 'Ext.data.Store',
autoload: true,
proxy: {
    type: 'ajax',
    url : 'data/getParams.py',
    reader: new Ext.data.JsonReader({
        fields:[]
    }),
    root: 'data'  
}

And to add series to the chart I did this :

var chart = Ext.widget('drawchart');
var fields = [];

chartStore.each(function (field) {
    fields.push(Ext.create('Ext.data.Field', {
        name: field.get('name')
    }));
});
chartModel.prototype.fields.removeAll();
chartModel.prototype.fields.addAll(fields);

var series = [];
for (var i = 1; i < fields.length; i++) {
    var newSeries = new Ext.chart.BarSeries({
        type: 'column',
        displayName: fields[i].name,
        xField: ['Month'],
        yField: fields[i].name,
        style: {
            mode: 'stretch',
            color: this.chartColors[i + 1]
        }
    });
    series.push(newSeries);
    chart.series = series;
};

chart.bindStore(chartStore);
chart.redraw();
chart.refresh();

But It's not working, I think the fields array is always empty... Any help would be appreciated:

I'm using Extjs 4 with the MVC architecture.

I have a python script that outputs this Json Data :

{
"data": [
    {
        "inAnalysis": 3, 
        "inQuest": 2, 
        "inDevelopment": 6, 
        "total": 12, 
        "inValidation": 1, 
        "Month": 1303
    }, 
    {
        "inAnalysis": 1, 
        "total": 5, 
        "Month": 1304, 
        "inDevelopment": 4
    }
], 
"success": true, 
"metaData": {
    "fields": [
        {
            "name": "inAnalysis"
        }, 
        {
            "name": "inQuest"
        }, 
        {
            "name": "inDevelopment"
        }, 
        {
            "name": "inValidation"
        }, 
        {
            "name": "isDuplicate"
        }, 
        {
            "name": "New"
        }, 
        {
            "name": "total"
        }
    ], 
    "root": "data"
}

}

I want the fields of my MetaData to be used as the chart series, so I have a store like this :

Ext.define('Proj.store.ChartData', {
extend: 'Ext.data.Store',
autoload: true,
proxy: {
    type: 'ajax',
    url : 'data/getParams.py',
    reader: new Ext.data.JsonReader({
        fields:[]
    }),
    root: 'data'  
}

And to add series to the chart I did this :

var chart = Ext.widget('drawchart');
var fields = [];

chartStore.each(function (field) {
    fields.push(Ext.create('Ext.data.Field', {
        name: field.get('name')
    }));
});
chartModel.prototype.fields.removeAll();
chartModel.prototype.fields.addAll(fields);

var series = [];
for (var i = 1; i < fields.length; i++) {
    var newSeries = new Ext.chart.BarSeries({
        type: 'column',
        displayName: fields[i].name,
        xField: ['Month'],
        yField: fields[i].name,
        style: {
            mode: 'stretch',
            color: this.chartColors[i + 1]
        }
    });
    series.push(newSeries);
    chart.series = series;
};

chart.bindStore(chartStore);
chart.redraw();
chart.refresh();

But It's not working, I think the fields array is always empty... Any help would be appreciated:

Share Improve this question edited Jul 21, 2014 at 22:42 Ben 1,36817 silver badges42 bronze badges asked Sep 27, 2013 at 14:56 salameysalamey 3,82110 gold badges40 silver badges71 bronze badges 2
  • Could you find any solution to your question? – Dhairya Vora Commented Feb 26, 2014 at 5:28
  • please paste your code on fiddle with dummy json – Man Programmer Commented Jul 22, 2014 at 10:18
Add a ment  | 

2 Answers 2

Reset to default 7 +25

Swapping or reloading a store would be easy, however you'd have a very hard time reconfiguring axes and series a posteriori... Ext's chart just don't support that. It would be possible to replace the axis in the myChart.axes collection, and same for series, and then with a careful study of the code, replace remove the existing sprites, etc. However that's a fool's path since, for once your code will be very fragile against future evolutions of Ext's chart code (which happen), and second there is a far more easier and reliable solution. That is creating a new chart, remove the old one, put the new one in its place, and pouf! The user won't see the difference.

You're not giving a lot of information about your code, so I'll work a solution out of the Bar chart example.

First, you need to fix your store:

Ext.define('Proj.store.ChartData', {
    extend: 'Ext.data.Store',
    //autoload: true,
    autoLoad: true, // there was a type in there
    fields: [], // was missing
    proxy: {
        type: 'ajax',
        url : 'data/getParams.py',
        // better to inline the proxy (lazy init)
        reader: {
            type: 'json'
            ,root: 'data' // and root is an option of the reader, not the proxy
        }
//      reader: new Ext.data.JsonReader({
//          fields:[]
//      }),
//      root: 'data'
    }
});

Then, let's enrich your response a bit in order to minimize the prior client-side knowledge of the model to none. I've added a totalField and a categoryField to the metaData node, that we'll use for the axis and series:

{
    "data": [
        {
            "inAnalysis": 3,
            "inQuest": 2,
            "inDevelopment": 6,
            "total": 12,
            "inValidation": 1,
            "Month": 1303
        },
        {
            "inAnalysis": 1,
            "total": 5,
            "Month": 1304,
            "inDevelopment": 4
        }
    ],
    "success": true,
    "metaData": {
        "totalField": "total",
        "categoryField": "Month",
        "fields": [
            {
                "name": "Month"
            },
            {
                "name": "inAnalysis"
            },
            {
                "name": "inQuest"
            },
            {
                "name": "inDevelopment"
            },
            {
                "name": "inValidation"
            },
            {
                "name": "isDuplicate"
            },
            {
                "name": "New"
            },
            {
                "name": "total"
            }
        ],
        "root": "data"
    }
}

Please, notice that the proxy will catch the metaData in the response automatically and reconfigure its store's (implicit) model accordingly... so you don't need your gloubiboulga to do it yourself. It is also worth noting that the reader will keep a copy of the raw response data in its rawData property; that will be useful to get the custom information we've added.

Now that we have a proper store that will receive a detailed response, let's use it:

new Proj.store.ChartData({
    listeners: {
        load: replaceChart
    }
});

That will trigger the replaceChart method, that will create a brand new chart from the meta and data given by the server and destroy and replace the old one. Here's the function:

function replaceChart(chartStore) {

    // Grab the name of the total & category fields as instructed by the server
    var meta = chartStore.getProxy().getReader().rawData.metaData,
        totalField = meta.totalField,
        categoryField = meta.categoryField;

    // Build a list of all field names, excluding the total & category ones
    var fields = Ext.Array.filter(
        Ext.pluck(chartStore.model.getFields(), 'name'),
        function(field) {
            return field !== categoryField && field !== totalField;
        }
    );

    // Create a pimping new chat like you like
    var chart = Ext.create('Ext.chart.Chart', {
        store: chartStore,
        legend: true,
        axes: [{
            type: 'Numeric',
            position: 'bottom',
            fields: [totalField]
        }, {
            type: 'Category',
            position: 'left',
            fields: [categoryField]
        }],
        series: [{
            type: 'bar',
            axis: 'bottom',
            label: {
                display: 'insideEnd',
                field: fields
            },
            xField: categoryField,
            yField: fields,
            stacked: true // or not... like you want!
        }]
    });

    // Put it in the exact same place as the old one, that will trigger
    // a refresh of the layout and a render of the chart
    var oldChart = win.down('chart'),
        oldIndex = win.items.indexOf(oldChart);
    win.remove(oldChart);
    win.insert(oldIndex, chart);

    // Mission plete.
}

Try to clear lines cache of unused series:

Ext.Array.each(chart.series.items, function(item){
            if(!item.items.length){
                item.line = null;
            }
        });
发布评论

评论列表(0)

  1. 暂无评论