OK, I admit it. I'm baffled. - Ext JS

本文详细介绍了从旧版ExtJS网格升级到新版的过程,包括如何使用新的数据模型、数据代理和读取器等组件。作者分享了具体的实现代码,如自定义DWRProxy和ListRangeReader,以及如何通过DWR获取数据并映射到Ext.data.Record。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

I want to upgrade to the new grid.

I've been reading source code, but going round in circles.

Using 0.33, I implemented my own custom DataModel which extended LoadableDataModel and used DWR to pull in this.data[][]. Dead easy!

And I had a custom ColumnModel (extends DefaultColumnModel) which pulled in a standard DefaultColumnModel config object down through DWR (The Java class GridColumn corresponds exactly to a column config object, so returning an array of these, I could just put the return value into this.config) Also dead easy.

Now, there's ext.data.Record, ext.data.DataField, ext.data.Store, ext.data.DataProxy.........

How does it all hang together?

I'm going to need to create my own extension of ext.data.Store (which is the new version of DataModel yes?) which provides the data by calling DWR. What is "this.data" a MixedCollection of? What does it provide? Using 0.33, it just provided cells from this.data[][] indexed by row and column.

The ext.data.Record looks just like the column model. Why is it there? Can I generate this from my column model like this:

//	Create the data record based on column headers.
	var recordEls = [];
    	for (var col in config) {
    		recordEls.push({name:col.header, mapping:col.header});
    	}
	this.dataRecord = Ext.data.Record.create(recordEls);
:?:
Reply With Quote
  #2  
Old 02-20-2007, 06:10 AM
Default

Animal,

You don't need to touch DataStore. It was specifically designed to be independent of the source of the data. What you need is a DataProxy (proxy's data from sources) and a Reader (read DWR objects into data.Records). Both those interfaces are very simple. The structure was defined so that you don't need to extend Store to provide data from sources other than the default 3.

The flow is like this:

Store calls proxy passing info about what to load. Proxy gets the data from wherever and then uses a reader to read it into record objects. It then calls back to the store with the new data who then notifies observers of the new data.

It may seem overly complex, but there is a reason - trust me.

--

The record class is very different than a ColumnModel. It defines the data structure/fields, while the ColumnModel defines the column's in a grid. While much of the time they may be similar, their properties are entirely different. Records can and will be used by more than just the grid.
Reply With Quote
  #3  
Old 02-20-2007, 06:17 AM
Default

OK then, looks like I need a DWRProxy, and a DWRReader. I'll look at existing ones to see what to do. Thanks!

OK, I get it about the records - you can have loads of fields in the record, but your ColumnModel might only use a few of them.
Reply With Quote
  #4  
Old 02-20-2007, 06:41 AM
Default

What methods does my DWRProxy have to implement? I've copied HttpProxy, but obviously there can be no getConnection()
Reply With Quote
  #5  
Old 02-20-2007, 07:33 AM
Default

Currently the only one called is load(), but the other update ones will eventually be there to automatically marshall saves.

The whole Connection stuff is specific to HttpProxy so you can ignore it.
Reply With Quote
  #6  
Old 02-20-2007, 07:53 AM
Default

OK, so "name" in Ext.data.Record.create() maps a record item onto the ColumnModel's "dataIndex" property?

And "mapping" in Ext.data.Record.create() is the index into the field collection? Because through DWR, I'm just returning a row as an Object[]

So I guess "mapping" will be 0, 1, 2....?
Reply With Quote
  #7  
Old 02-20-2007, 08:09 AM
Default

So it's the "params" parameter passed to load() that specified page number and size etc?
[/code]
Reply With Quote
  #8  
Old 02-20-2007, 08:51 AM
Default

I guess. I'm not very familiar with DWR responses.

The column model (or later, form fields) can bind to fields in a record via dataIndex=>named field.

Incoming data can be mapped into fields via mapping => field. If you are using a default reader, you could skip the mapping stage, but that's up to you.

The params passed to load will contain start, limit and optionally any sorting information.
Reply With Quote
  #9  
Old 02-20-2007, 10:00 AM
Default

OK, so what I send back from the DWR call getRange(int start, int limit) is this object:

public class ListRange
{
	private long totalRows;
	private Object[] data; // Each element, is in fact an Object[]
	public ListRange() {
		this.totalRows = 0;
		this.data = new Object[]{};
	}
	public ListRange(long totalRows, Object[] data) {
		this.totalRows = totalRows;
		this.data = data;
	}
	public void setData(Object[] data) {
		this.data = data;
	}
	public Object[] getData() {
		return data;
	}
	public void setTotalRows(int totalRows) {
		this.totalRows = totalRows;
	}
	public long getTotalRows() {
		return totalRows;
	}
}
DWR marshalls that into a javascript object, so the DWRProxy looks like this:

aspicio.DWRProxy = function(listerId) {
    this.listerId = listerId;
    aspicio.DWRProxy.superclass.constructor.call(this);
};

Ext.extend(aspicio.DWRProxy, Ext.data.DataProxy, {
    load : function(params, reader, callback, scope, arg){
        if(this.fireEvent("beforeload", this, params) !== false){
			ListHelper.getRange(this.listerId, params.start, params.limit,
				this.loadResponse.createDelegate(this, [reader, callback, scope, arg], 1));
        }else{
            callback.call(scope||this, null, arg, false);
        }
    },
    
    loadResponse : function(listRange, reader, callback, scope, arg){
        var result;
        try {
            result = reader.read(listRange);
        }catch(e) {
            this.fireEvent("loadexception", this, null, response, e);
            callback.call(scope, null, arg, false);
            return;
        }
        callback.call(scope, result, arg, true);
    },
    
    update : function(dataSet){
        
    },
    
    updateResponse : function(dataSet){
        
    }
});
The reader looks like this:

aspicio.ListRangeReader = function(meta, recordType){
    Ext.data.ListRangeReader.superclass.constructor.call(this, meta, recordType);
};
Ext.extend(aspicio.ListRangeReader, Ext.data.DataReader, {
    readRecords : function(o){
        var sid = this.meta ? this.meta.id : null;
    	var recordType = this.recordType, fields = recordType.prototype.fields;
    	var records = [];
    	var root = o.data;
	    for(var i = 0; i < root.length; i++){
		    var n = root[i];
	        var values = {};
	        var id = (sid && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
	        for(var j = 0, jlen = fields.length; j < jlen; j++){
                var f = fields.items[j];
                var k = f.mapping || j;
                var v = n[k] !== undefined ? n[k] : f.defaultValue;
                v = f.convert(v);
                values[f.name] = v;
            }
	        var record = new recordType(values, id);
	        records[records.length] = record;
	    }
	    return {
	        records : records,
	        totalRecords : o.totalRows
	    };
    }
});
which is created like this:

//	    Create reader that can read a com.aspicio.util.ListRange
	    this.reader = new aspicio.ListRangeReader({ id: 0 }, this.columnModel.dataRecord);
Because the ColumnModel knows about the data, so it creates the Ext.data.Record:

//	Create the data record which just uses numeric indices into an Object Array.
//	Do not include the uuid field which is always present as the id. All other
//	columns are valid data fields.
	var recordEls = [];
	var colIdx = 0;
    	for (var col in config) {
    		if (col.name != "uuid") { // Skip the uuid
	    		recordEls.push({name:col.dataIndex, mapping:colIdx});
	    		colIdx++;
	    	}
    	}
	this.dataRecord = Ext.data.Record.create(recordEls);
What can possibly go wrong? :lol: :lol: :lol: :lol: :lol: :lol:
Reply With Quote
  #10  
Old 02-20-2007, 10:09 AM
Default

Nothing obvious jumping out at me. Any errors?

FYI, I can't tell you how much you code has improved in the past few months. That's some clean looking code! Even your brackets are in the "right" spot.
Reply With Quote
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值