Tuesday, September 30, 2014

Ext JS CSV Data Reader

In a previous post, I showed how you can convert CSV to JSON in JavaScript. In this post, I will show how you can display CSV data in an Ext JS grid panel using a custom Reader.

Currently, there are three kinds of Readers available in Ext JS 4.2.2:

A CSV reader isn't available but is quite easy to create, simply by extending the JSON reader. The code for my CSV Reader is shown below. It first converts the CSV response from the server into JSON format and then invokes the parent JSON reader.

/**
 * The CSV Reader is used by a Proxy to read a server response
 * that is sent back in CSV format.
 */
Ext.define('CsvReader', {
    extend: 'Ext.data.reader.Json',
    alias : 'reader.csv',

    // converts csv into json
    toJson: function(csvData){
      var lines = csvData.split("\n");
      var colNames = lines[0].split(",");
      var records = [];
      for(var i = 1; i < lines.length; i++) {
        if (lines[i] == "") continue;
        var record = {};
        var bits = lines[i].split(",");
        for (var j = 0; j < bits.length; j++) {
          record[colNames[j]] = bits[j];
        }
        records.push(record);
      }
      return records;
    },

    // override
    getResponseData: function(response) {
        try {
            return this.readRecords(response.responseText);
        } catch (ex) {
            error = new Ext.data.ResultSet({
                total  : 0,
                count  : 0,
                records: [],
                success: false,
                message: ex.message
            });
            this.fireEvent('exception', this, response, error);
            console.log(error);
            return error;
        }
    },

    // override
    readRecords: function(strData) {
        var result = this.toJson(strData);
        return this.callParent([result]);
    }
});

Now let's use it to display an example CSV file containing book data in a grid.

author,title,publishDate
Dan Simmons,Hyperion,1989
Douglas Adams,The Hitchhiker's Guide to the Galaxy,1979

Here is some sample code to read the CSV file into a grid using the CSV reader defined above:

Ext.define('Book', {
    extend: 'Ext.data.Model',
    fields: [
        {name: 'author', type: 'string'},
        {name: 'title', type: 'string'},
        {name: 'publishDate', type: 'string'}
    ]
});

var bookStore = Ext.create('Ext.data.Store', {
    model: 'Book',
    autoLoad: true,
    proxy: {
        type: 'ajax',
        reader: 'csv',
        url: 'data.csv'
    }
});

Ext.application({
    name: 'MyApp',
    launch: function() {
        Ext.create('Ext.Viewport', {
            layout: 'fit',
            items: [{
                xtype:'grid',
                title: 'Books',
                store: bookStore,
                columns: [
                   { text: 'Author', dataIndex: 'author' },
                   { text: 'Title', dataIndex: 'title', flex:1 },
                   { text: 'Publish Date', dataIndex: 'publishDate' }
                ],
                height: 200,
                width: 400
            }],
            renderTo: Ext.getBody()
        });
    }
});

Related posts:
Converting CSV to JSON in JavaScript

2 comments:

  1. I made a simple implementation of your custom reader but I am unable to access the data it returns, as I can see the data but the extJS does recognize the data, as mapping it into objects for the view model seems impossible. Please a little pointer in the right direction will go a long way. thanks

    Ext.define('School.model.CsvReader', {
    extend: 'Ext.data.reader.Json',
    alias : 'reader.csv',

    // converts csv into json
    toJson: function(csvData){
    var stringCSV = String(csvData);
    var lines = stringCSV.split("\n");
    for(var l = 0;l < lines.length; l++){
    var lineBreak = lines[l];
    lineBreak = lineBreak.replace(/(\r\n|\n|\r)/gm,"");
    lines[l] = lineBreak;
    }

    var records = [];
    var headers=lines[0].split(";");
    var realLength = lines.length - 1;

    for(var i=1;i<realLength;i++){
    var obj = {};
    var currentline=lines[i].split(";");

    for(var j=0;j<headers.length;j++){
    obj[headers[j]] = currentline[j];
    }
    records.push(obj);
    }
    return records;
    },

    // override
    getResponseData: function(response) {
    try {
    return this.readRecords(response.responseText);
    } catch (ex) {
    error = new Ext.data.ResultSet({
    total : 0,
    count : 0,
    records: [],
    success: false,
    message: ex.message
    });
    this.fireEvent('exception', this, response, error);
    console.log(error);
    return error;
    }
    },

    // override
    readRecords: function(strData) {
    var result = this.toJson(strData);
    //var bed = [result];
    var myJsonString = JSON.stringify(result);
    var obj = JSON.parse(myJsonString);
    var q = new Array(result);
    console.log(obj, result);

    return this.callParent(q);
    }
    });


    ReplyDelete