views:

187

answers:

1

Hi,

I have an ExtJS EditorGridPanel with several columns. One of the columns is bound to a complex data type (an array of objects), and uses a custom editor to modify those values in a pop-up window. That part is tested and all works fine - the JsonStore is keeping the complex values, setting the custom editor's value when it's focused and editing begins, and picking up the final value when editing is complete.

The only problem is, for this complex data type, the Javascript string value does not appear to include the sub-attributes, but is instead represented as "[object Object]". Therefore, if the array contains two items when editing begins, and two items after editing is complete, even if some of the sub-attributes of the two items have changed, the grid editor doesn't know this, because (String)value === (String)startValue (that is, '[object Object],[object Object]' === '[object Object],[object Object]').

I'm certain this is the problem, because if the custom sub-editor increases the number of items in the list, the string values are different ('[object Object],[object Object],[object Object]' !== '[object Object],[object Object]'), and the value properly changes (with change event propagating to the store).

The complete onEditComplete function of the EditorGridPanel is shown below (full source here):

onEditComplete : function(ed, value, startValue){
    this.editing = false;
    this.lastActiveEditor = this.activeEditor;
    this.activeEditor = null;

    var r = ed.record,
        field = this.colModel.getDataIndex(ed.col);
    value = this.postEditValue(value, startValue, r, field);
    if(this.forceValidation === true || String(value) !== String(startValue)){
        var e = {
            grid: this,
            record: r,
            field: field,
            originalValue: startValue,
            value: value,
            row: ed.row,
            column: ed.col,
            cancel:false
        };
        if(this.fireEvent("validateedit", e) !== false && !e.cancel && String(value) !== String(startValue)){
            r.set(field, e.value);
            delete e.cancel;
            this.fireEvent("afteredit", e);
        }
    }
    this.view.focusCell(ed.row, ed.col);
},

So there are a number of possible solutions, but I don't know how to make any of them work.

  1. Provide a custom GridEditor for this particular column of the EditorGrid, which considers the startValue to always be some dummy value, so that the String(value) !== String(startValue)) clause above is always true. This seems difficult because you don't have access to the GridEditor from within the custom field (since it is in the Field hierarchy and doesn't know about the GridEditor controlling it).
  2. Somehow get a handle on the GridEditor being used to control my custom Field, from some kind of event. If I can do that, I can set the startValue (a public property) to some dummy value that is known to be different from the final value. Then the normal "changed value" code will work as expected. I haven't found any reasonable way to get a handle to this editor from within my field, however.
  3. Convince Javascript to spit out all of the sub-attributes of my objects into the String representation, so that if my object is

var myObj = { 'objId': 1, 'objValue': value };

var myValue = [myObj];

then instead of (String)myValue being '[object Object]', it will instead be something like '[{objId:1,objValue:value}]'.

A: 

Nevermind, it appears that I wasn't correctly adding the toString() function to my objects. Doing so fixes the problem.

var myObj = {'objId':1,'objValue':'value'};
myObj.toString = function(){ return String.format('MyObj {objId:{0},objValue:{1}}',this.objId,this.objValue);};

var myValue = [myObj];

Now, the String value of myValue above is [MyObj {objId:1,objValue:value}] instead of [object Object]and the problem is solved - the GridEditor correctly updates the record when any one of the underlying objects' attributes have changed.

jeff303