Opened 8 years ago

Closed 6 years ago

#15336 closed defect (duplicate)

1.8 JsonRest+ObjectStoreModel+Tree+Observable delete a item in store, but the tree node cannot auto remove

Reported by: jzw Owned by: Kris Zyp
Priority: undecided Milestone: tbd
Component: Data Version: 1.7.2
Keywords: Cc:
Blocked By: Blocking:

Description

hi, in "dijit/tests/tree/Tree_ObjectStoreModel.html", use dojo/store/Memory, when remove or put data, the tree can update(delete or add a node in the tree),but when use dojo/store/JsonRest instead, it not works.

below is my code and server side response data

define(["dijit/Tree",
        "dojo/store/JsonRest",
        "dijit/tree/ObjectStoreModel",
        "dojo/store/Observable"],function(
        		Tree,
        		JsonRest,
        		ObjectStoreModel,
        		Observable){
	jsonRest = new JsonRest({
		target:"/items/",
		getChildren: function(object){
			return this.query(object.id);
        }
	});
	jsonRest = Observable(jsonRest);
	var treeModel = new  ObjectStoreModel({
        store: jsonRest,
		query:"root",
		mayHaveChildren: function(item){
			return item.children==true;
		}
   	});
	tree = new Tree({
		model : treeModel,
		persist:false
	},"treeDiv");
	tree.startup();
	
	function removeSelectedNode(){
		var selectItem = tree.get("selectedItem");
		jsonRest.remove(selectItem.id);
	}
});


server side response data.

target:data/root

[
{id:1,name:'n1',children:true, parent:'root'},
{id:2,name:'n2',children:true, parent:'root'}
]

but when i select a node and execute removeSelectedNode() function, in server side ,the data is delete success,but in browser the node is still there quietly and smile at me( :( ).

Did I miss something, or it's a bug? thanks

Change History (8)

comment:1 Changed 8 years ago by bill

Component: GeneralData
Owner: set to Kris Zyp

My guess is that Observable is not giving a notification that the item was deleted.

comment:2 Changed 8 years ago by jzw

trace the code, found "children.observe" is undefined in dijit/tree/ObjectStoreModel。
line 246

if(children.observe){
//code
}

and in dojox/store/Observable line 67 resultsArray.length always = 0 so the follow code never runs

// remove the old one
for(i = 0, l = resultsArray.length; i < l; i++){
	var object = resultsArray[i];
	if(store.getIdentity(object) == existingId){
		removedObject = object;
		removedFrom = i;
		if(queryExecutor || !changed){
			resultsArray.splice(i, 1);
		}
		break;
	}
}

isn't it?

Last edited 8 years ago by jzw (previous) (diff)

comment:3 Changed 7 years ago by cjong

Hi,

I've been playing around with objectStoreModel in 1.8.0b1 and ran into a similar problem. I think I know what's causing this.

The objectStoreModel assumes the result of this.store.getChildren() is an array, however if your working with a jsonRest the result will be a queryResult.

This how I resolved the issue:

from line 129 in getChildren

Code highlighting:

// Setup listener in case children list changes, or the item(s) in the children list are
// updated in some way.
// FIX: replace children with this.childrenCache[id]
if(this.childrenCache[id].observe){
    // FIX: replace children wirh this.childrenCache[id]
    this.childrenCache[id].observe(lang.hitch(this, function(obj, removedFrom, insertedInto){
    console.log("observe on children of ", id, ": ", obj, removedFrom, insertedInto);
    ...
))}

and in pasteItem

Code highlighting:

if(!bCopy){
var queryResult = this.childrenCache[this.getIdentity(oldParentItem)];
Deferred.when(queryResult, lang.hitch(this, function(oldParentChildren){ 
    index = array.indexOf(oldParentChildren, childItem);
    oldParentChildren.splice(index, 1);
    this.onChildrenChange(oldParentItem, oldParentChildren);
}));
}

Hope this helps.

comment:4 Changed 6 years ago by sutabi

Looks like this is still an issue with 1.9. getChildren seems to work, but pasteItem - when using drag and drop plus JsonRest?, doesn't work. The code cjong used didn't work for me when moving the node within the same parentItem. Change I did allows sorting between the same parentItem, but there still is an issue with moving nodes around. When you move a node outside a parentItem, it is never added to the newParentItem. However if you move a node inside a parent (could be nested), it will work. If I can get that to work I will post some newer code.

if (!bCopy) {
	if (oldParentItem === newParentItem) {
		var res = this.childrenCache[this.getIdentity(oldParentItem)];
		when(res, lang.hitch(this, function (oldParentChildren) {
			var old_index = array.indexOf(oldParentChildren, childItem);
			var new_index = insertIndex;
			if (new_index >= oldParentChildren.length) {
				var k = new_index - oldParentChildren.length;
				while ((k--) + 1) {
					oldParentChildren.push(undefined);
				}
			}
			oldParentChildren.splice(new_index, 0, oldParentChildren.splice(old_index, 1)[0]);
			this.onChildrenChange(oldParentItem, oldParentChildren);
		}));
	} else {
		var res = this.childrenCache[this.getIdentity(oldParentItem)];
		when(res, lang.hitch(this, function(oldParentChildren){ 
			var index = array.indexOf(oldParentChildren, childItem);
			oldParentChildren.splice(index, 1);
			this.onChildrenChange(oldParentItem, oldParentChildren);
		}));
	}
}

comment:5 Changed 6 years ago by sutabi

Okay, here is a better version that for the most part fixes everything for 1.9.

What's Still broken:

  • The icons do not change they now have children or no children
  • If you drag and drop multiple items at the same time, the last item (if it is greater than two items) is never moved. There is an error happening saying it has no parent...
if (!bCopy) {
        oldParentId = this.getIdentity(oldParentItem);
        newParentId = this.getIdentity(newParentItem);

        oldParentChildrenCache = this.childrenCache[oldParentId];
        newParentChildrenCache = this.childrenCache[newParentId];

        when(oldParentChildrenCache, lang.hitch(this, function (oldParentChildren) {
                if (oldParentItem === newParentItem) {
                        //-- This is the same parent
                        var lastIndex = array.indexOf(oldParentChildren, childItem);
                        oldParentChildren.splice(insertIndex, 0, oldParentChildren.splice(lastIndex, 1)[0]);
                } else {
                        var index = array.indexOf(oldParentChildren, childItem);
                        oldParentChildren.splice(index, 1);
                }
                this.onChildrenChange(oldParentItem, oldParentChildren);

                if (oldParentItem !== newParentItem) {
                        //-- Add in the newer copy
                        when(newParentChildrenCache, lang.hitch(this, function(newParentChildren) {
                                childItem.parent = newParentItem.id;
                                if (newParentChildren == null) {
                                        newParentChildren = [];
                                }
                                newParentChildren.splice(insertIndex, 0, childItem);
                                this.onChildrenChange(newParentItem, newParentChildren);
                        }));
                }
        }));
}

I also found that if you place an item, below a folder, the folder expands. dijit/tree/dndSource.js -> onDndDrop

So I made this change to that file:

onDndDrop: function(source, nodes, copy){
        var expandOver = false;
        if(this.containerState == "Over"){
                ...
                if(this.dropPosition == "Before" || this.dropPosition == "After"){
                        ...
                }else{
                        ...
                        expandOver = true;
                }
                ...
                if (expandOver) {
                        this.tree._expandNode(target);
                }
        }
        this.onDndCancel();
},

comment:6 Changed 6 years ago by Wouter Hager

Disappointed to see this issue is still not fixed. We're in 1.9.3 now and I still don't see an update of the tree after putting a new child.

comment:7 Changed 6 years ago by Tomas236

I have almost same problem. I have tree connected with jsonrest store wrapped in Observable. When I query, I get new data, but Tree won't refresh. Going to write new bug report, mb some1 will get look at it ;-)

comment:8 Changed 6 years ago by bill

Resolution: duplicate
Status: newclosed

Duplicate of #17783.

Note: See TracTickets for help on using tickets.