Showing posts with label extjs. Show all posts
Showing posts with label extjs. Show all posts

Saturday, January 23, 2016

Ext JS - Changing the "Today" button in a date field

The datefield in Ext JS has a date picker dropdown containing a handy "Today" button, which allows you to quickly select today's date. But what if you're not interested in today's date? This post shows how you can change the text and the handler of the "Today" button in order to select a different date e.g. yesterday.

My jsfiddle for changing the "Today" button is embedded below. After the date field has been rendered, it gets a reference to the Today button via the date field's picker object and then changes its handler to select yesterday's date instead.

Saturday, March 28, 2015

Ext JS - Reading a JSON File

This post shows how you can read a JSON file in your Ext JS applications.

Let's say you have the following person.json file, which contains information about a person:

{
    "name" : "Joe Bloggs",
    "age"  : "15"
}

In order to load this file, you need to define an Ext.data.Store as shown below:

Ext.define('MyApp.store.Person', {
    extend: 'Ext.data.Store',
    fields: ['name', 'age'],
    autoLoad: true,
    proxy: {
        type: 'ajax',
        url: 'person.json',
        reader: 'json',
        pageParam: false,
        startParam: false,
        limitParam: false,
        noCache: false,
        listeners: {
            exception: function(proxy, response, operation) {
                // add appropriate error handling!
                console.log("Could not read file");
            }
        }
    },

    // return the specified field of the person e.g. name.
    get: function(field) {
        return this.first() && this.first().get(field);
    }
});

Then create the store and once it has loaded, you can access the data.

var store = Ext.create('MyApp.store.Person');
store.on('load', function() {
    console.log(store.get('name'));
});

Sunday, November 30, 2014

Logging the Duration of Ext Ajax Requests

The following snippet shows how to log the duration of ajax requests in your Ext JS application:

Ext.Ajax.on('beforerequest', function(conn, response, options){
    console.log("Requesting:" + response.url);
    console.time(response.url);
});
Ext.Ajax.on('requestcomplete', function(conn, response, options){
    console.timeEnd(options.url);
});

Note that this code uses console.time(), which is a non-standard feature and may not work in all browsers.

Saturday, November 22, 2014

Ext JS - Caching AJAX Responses to HTML5 Web Storage for Better Performance

This post shows how you can improve performance of your Ext JS applications by using a "Caching AJAX Proxy". This proxy saves URL responses to HTML5 Web Storage (e.g. session storage or local storage), which means that when the same URL is requested multiple times, a cached response is returned, instead of sending a request to the server each time. This makes the application more responsive and also reduces load on the server handling the requests.

/**
 * A Caching Ajax Proxy which uses AJAX requests to get data from a server and
 * then stores the data to HTML5 Web Storage. If the storage fills up, it removes
 * entries from the cache until space is available.
 * (Compatible with Ext JS 4.2)
 */
Ext.define('App.data.proxy.CachingAjax', {
  extend: 'Ext.data.proxy.Ajax',
  alias: 'proxy.cachingajax',

  // use session storage, but can be configured to localStorage too
  storage: window.sessionStorage,

  // @Override
  doRequest: function(operation, callback, scope) {
    var cachedResponse = this.getItemFromCache(this.url);
    if (!cachedResponse) {
        this.callParent(arguments);
    }
    else {
        console.log('Got cached data for: ' + this.url);
        this.processResponse(true, operation, null, cachedResponse,
                             callback, scope, true);
    }
  },

  // @Override
  processResponse: function(success, operation, request, response,
                            callback, scope, isCached) {
    if (success === true && !isCached) {
        this.putItemInCache(this.url, response.responseText);
    }
    this.callParent(arguments);
  },

  /**
   * @private
   * Returns the data from the cache for the specified key
   * @param {String} the url
   * @return {String} the cached url response, or null if not in cache
   */
  getItemFromCache: function(key) {
    return this.storage ? this.storage.getItem(key) : null;
  },

  /**
   * @private
   * Puts an entry in the cache.
   * Removes a third of the entries if the cache is full.
   * @param {String} the url
   * @param {String} the data
   */
  putItemInCache: function(key, value) {
    if (!this.storage) return;
    try {
      this.storage.setItem(key, value);
    } catch (e) {
      // this might happen if the storage is full.
      // Remove a third of the items and retry.
      // If it fails again, disable the cache quietly.
      console.log('Error putting data in cache. CacheSize: ' + this.storage.length +
                  ', ErrorCode: ' + e.code + ', Message: ' + e.name);

      while (this.storage.length != 0) {
        var toRemove = this.storage.length / 3;
        for (var i = 0; i < toRemove ; i++) {
          var item = this.storage.key(0);
          if (item) this.storage.removeItem(item);
          else break;
        }
        console.log('Removed one-third of the cache. Cache size is now: ' + this.storage.length);
        try {
          this.storage.setItem(key, value);
          break;
        } catch (e) {
          console.log('Error putting data in cache again. CacheSize: ' + this.storage.length +
                      ', ErrorCode: ' + e.code + ', Message: ' + e.name);
        }
      }
      if (this.storage.length == 0) {
        console.log("Cache disabled");
        this.storage = null;
      }
    }
  }
});
Usage:
var store = Ext.create('Ext.data.Store', {
  model: 'User',
  proxy: {
    type: 'cachingajax',
    url : 'http://mywebsite/path'
  }
});

Obviously, you should only use this caching proxy when the server-side data is static, because if it is changing frequently your application will end up displaying stale, cached data.

This proxy can also be extended in the future to remove cached entries after specific time intervals or clear out the entire cache when the application starts up.

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