1
votes

I have a grid and a store. The store gets populated with some data - country - while the rest is empty. Once I receive more inputs I fill up the store with the inputs.

Assume that I have only 1 country in the store after the initial load.

Store:

feedTheGrid = new Ext.data.JsonStore({
    autoDestroy : true,
    autoSave : false,
    autoLoad : true,
    idProperty: 'country',
    root: 'root',
    totalProperty : 'totalcount',
    fields : ['country', 'towns'],
    proxy : new Ext.data.HttpProxy(new Ext.data.Connection({
        url : "country/searchCountries.action",
        method : 'POST',
        timeout : 300000
    }))
});

So the user inputs towns. I save a town in the array towns using push():

listeners: {
    'change': function() {
        if (feedTheGrid.getAt(0).towns === undefined) {
            feedTheGrid.getAt(0).towns = [];
        }
        feedTheGrid.getAt(0).towns.push(this.getValue());
        gridMonster.getView().refresh();
    }
}

I want the grid to update every time a new town is put in.

This is part of the column model I use for gridMonster:

{ header: "Town 1", width: 150, dataIndex: 'towns', 
  renderer: function(val) {
      if (val[0] != undefined) {
          return val[0];
      }
  }, sortable: true},
{ header: "Town 2", width: 150, dataIndex: 'towns',
  renderer: function(val) {
      if (val[1] != undefined) {
          return val[1];
      }
  }, sortable: true},  
{ header: "Town 3", width: 150, dataIndex: 'towns',
  renderer: function(val) {
      if (val[2] != undefined) {
          return val[2];
      }
  }, sortable: true}

The issue is that after a town is put in the grid never refreshes.

Some things I noticed so far:

The store gets updated with the new value when I check through Firebug. Also it seems the val that is given in renderer is always empty String, even after I push the new value into the array and refresh the grid view.

I am using ExtJS 3.3.1

I know its old so I am open to solutions that would work for 4.0+ and I can try to apply it to 3.3.1.

EDIT: Found the issue

Very subtle problem, spent hours trying to find what is the problem only to find out I was looking in the wrong place. The issue was in this line:

feedTheGrid.getAt(0).towns.push(this.getValue());

This line actually creates a new field towns as part of the record that you get using getAt(0). Using firebug to see if getAt(0).towns[0] is populated actually returns the value you pushed which is misleading.

ExtJS is not aware of this new field and it shouldn't be.

This line should be:

feedTheGrid.getAt(0).data.towns.push(this.getValue());

The trick is to point at the right place: .data. Javascript/ExtJS allows you to add new field without any warning because technically you are not doing anything wrong. Logically it creates a new field that does nothing.

@Lorenz Meyer I am able to display elements of the array using renderer while pointing at towns array in the column model.

3
Why do you have 3 columns all containing a town? A grid should have columns that refer each to a field of a record in the store. - Lorenz Meyer
each column is an element of the array. - Code Whisperer
I think having multiple columns mapping to the same member (dataIndex) may be a problem. Checked the console for errors ? - Francis Ducharme
@FrancisDucharme no errors in console. Check edit for solution - Code Whisperer

3 Answers

2
votes

There is a major misunderstanding about what a store and a grid are in ExtJs.

Both are just a representation of tabular data. A store is the representation in memory of a table, in order to get fast access to records filtering and more features. A grid is the visual representation of a table in the browser window.

Such a table could look like :

Id | Country | City
-------------------
1  | US      | NYC
2  | France  | Macon
3  | US      | Macon

First of all on one table row, you can only have one city. In tables, you cannot have an array in a single field. If you have more than one city, this is what rows are for.

Then, your idProperty cannot be the country. If it were, this would mean that countries are unique. Obviously, they aren't. There can be more than one city in a country. (cities cannot be the idProperty neither, because there exists more than one city with the same).

Now you certainly begin to understand, that feedTheGrid.getAt(0).towns.push(this.getValue()); makes no sense whatever. The towns column cannot be an array. You insert a new row with feedTheGrid.add({country: 'US', towns: 'LA'}).
At best the towns column can be a comma separated value, in which case, you update the store with

var record = feedTheGrid.getAt(0),
currentTowns = record.get('towns');
record.set('towns', currentTowns + ', ' + value)

The method set of the record does all the magic: It passes the update event to the grid in order to rerender it. Your push in addition to be wrong will not trigger the events necessary to update the view.

About the grid: The columns of your grid should be:

{ header: "Id", width: 150, dataIndex: 'id', sortable: true},
{ header: "Country", width: 150, dataIndex: 'country', sortable: true},  
{ header: "Town(s)", width: 150, dataIndex: 'towns', sortable: true}

Notes:

  • That listeners: looks really strange to me, but maybe it's just because the bigger picture is missing.
  • feedTheGrid is a strange name for a store. The store does not feed the data. It is tha data.
  • A renderer alway must return a value, else the cell will remain blank. Therefore your renderers cannot work.
1
votes

In your renderers the val can not be an array. It's a simple variable. That's why your grid is not refreshing.

0
votes

Very subtle problem, spent hours trying to find what is the problem only to find out I was looking in the wrong place. The issue was in this line:

feedTheGrid.getAt(0).towns.push(this.getValue());

This line actually creates a new field towns as part of the record that you get using getAt(0). Using firebug to see if getAt(0).towns[0] is populated actually returns the value you pushed which is misleading.

ExtJS is not aware of this new field and it shouldn't be.

This line should be:

feedTheGrid.getAt(0).data.towns.push(this.getValue());

The trick is to point at the right place: .data. Javascript/ExtJS allows you to add new field without any warning because technically you are not doing anything wrong. Logically it creates a new field that does nothing.

@Lorenz Meyer I am able to display elements of the array using renderer while pointing at towns array in the column model.