Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ExtJS TreeStore update event fire instead of create

Tags:

extjs4

I am using tree.Panel with TreeStore when I call

sel_node.parentNode.appendChild(node);
tree.getSampleStore().sync();

ExtJS fire event called sample store proxy: update url instead of create url what could I have done wrong?

like image 389
c.sokun Avatar asked Oct 09 '22 03:10

c.sokun


1 Answers

What exact version of ExtJS4 do you use?

In my situation, with ext-4.0.7-gpl, I debugged a bit a found out that appendChild method creates a node from and object and then performs some update operations concerning the node's position in the tree, like setting next sibling, parent etc., see [1].

When syncing, the store uses getUpdatedRecords and getNewRecords [2] methods to determine which operation to run. update or create. Somehow, our appended children turn out to be updated, not created.

Note that the method doesn't check whether the children of a parent node was loaded, just pushes the new node into an empty childNodes array; after all these operations end, other children of a parent node are never shown in the tree; and if the update operation caused the serverside generation of new id, the code breaks on the line original = me.tree.getNodeById(record.getId()); - there is no such node with the old id generated on client side..

Simply put, I think it's a bug.

[1] http://docs.sencha.com/ext-js/4-0/source/NodeInterface.html#Ext-data-NodeInterface-method-appendChild [2] http://docs.sencha.com/ext-js/4-0/source/AbstractStore.html#Ext-data-AbstractStore-method-getUpdatedRecords

Add: ExtJS 4.1 beta 2 doesn't work better for me

Update with temp solution: I hacked a bit and think I solved the issue by overriding the appendChild method of NodeInterface like below (just to set phantom property so that the record becomes created, not updated).

Please note: 1) You should include your appendChild call in the NodeInterface expand method callback, or the bug with pushing to the empty childNodes will remain: the new node will appear somewhere in the wrong place; 2) I had to override updateIndexes of the AbstractView as well, try not to do this and maybe you'll find out why; 3) there are some issues when the store tries to delete our newly created node the next time it syncs - couldn't trace it yet; 0) I am no way ExtJS or even JS guru, so feel free to correct this hack)

Ext.data.NodeInterface.oldGpv = Ext.data.NodeInterface.getPrototypeBody;
Ext.data.NodeInterface.getPrototypeBody = function(){
    var ret = Ext.data.NodeInterface.oldGpv.apply(this, arguments);

    ret.appendChild = function(node, suppressEvents, suppressNodeUpdate) {
        var me = this,
        i, ln,
        index,
        oldParent,
        ps;


        if (Ext.isArray(node)) {
            for (i = 0, ln = node.length; i < ln; i++) {
                me.appendChild(node[i]);
            }
        } else {
            node = me.createNode(node);

            if (suppressEvents !== true && me.fireEvent("beforeappend", me, node) === false) {
                return false;
            }

            index = me.childNodes.length;
            oldParent = node.parentNode;

            if (oldParent) {
                if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index) === false) {
                    return false;
                }
                oldParent.removeChild(node, null, false, true);
            }else{
                node.phantom = true;
            }

            if(me.isLoaded()){
                index = me.childNodes.length;
                if (index === 0) {
                    me.setFirstChild(node);
                }

                me.childNodes.push(node);
                node.parentNode = me;
                node.nextSibling = null;

                me.setLastChild(node);

                ps = me.childNodes[index - 1];
                if (ps) {
                    node.previousSibling = ps;
                    ps.nextSibling = node;
                    ps.updateInfo(suppressNodeUpdate);
                } else {
                    node.previousSibling = null;
                }
                node.updateInfo(suppressNodeUpdate);
            }

            //console.log('appendChild was called');

            // I don't know what this code mean even given the comment
            // in ExtJS native source, commented out

            // As soon as we append a child to this node, we are loaded
            //if (!me.isLoaded()) {
            //    me.set('loaded', true);
            //}

            // If this node didnt have any childnodes before, update myself
            //else 
            //if (me.childNodes.length === 1) {
            //    me.set('loaded', me.isLoaded());
            //}

            if (suppressEvents !== true) {
                me.fireEvent("append", me, node, index);

                if (oldParent) {
                    node.fireEvent("move", node, oldParent, me, index);
                }
            }

            return node;
        }
    };
    return ret;
};

this is my code to add a node by values taken from a form domainForm. The form opens by clicking an icon in an actioncolumn of our tree grid:

var node = grid.store.getAt(rowIndex);
node.expand(false, function(){
    var newDomain = domainForm.getValues();
    newDomain.parent = {id: node.raw.id}; // i don't know whether you'll need this
    var newNode = node.appendChild(newDomain);
    me.store.sync();
});

and updateIndexes overrider:

Ext.override(Ext.view.AbstractView, {
    updateIndexes : function(startIndex, endIndex) {
        var ns = this.all.elements,
            records = this.store.getRange(),
            i;

        startIndex = startIndex || 0;
        endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length < records.length?(ns.length - 1):records.length-1) );
        for(i = startIndex; i <= endIndex; i++){
            ns[i].viewIndex = i;
            ns[i].viewRecordId = records[i].internalId;
            if (!ns[i].boundView) {
                ns[i].boundView = this.id;
            }
        }
    }    
});
like image 196
fedd Avatar answered Oct 14 '22 03:10

fedd