Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    TreeGrid edit - initial value not shown

    Hi All,

    I have a TreeGrid linked to a RestDataSource but when I initiate an edit with startEditing() the editor presents an empty cell rather than showing the existing value.

    Any pointers to what I'm doing wrong would be gratefully received.

    The following code shows it happening with a newly added record but it happens when editing existing records too.

    Code:
    isc.RestDataSource.create({
            ID: "menu",
            dataFormat: "json",
            dataURL: "menu.ashx",
            nameProperty: "name",
            idField: "id",
            parentIdField: "parentId",
            treeRootValue: 1,
            fields: [{
                name: "name",
                title: "Name",
                type: "text",
                canEdit: true,
                required: true
            }, {
                name: "id",
                title: "ID",
                type: "integer",
                primaryKey: true,
                canEdit: false,
                hidden: true,
                required: true
            }, {
                name: "parentId",
                title: "parentId",
                type: "integer",
                canEdit: false,
                hidden: true,
                required: true
            }
            ],
            transformRequest: function (dsRequest) {
                var data = this.Super("transformRequest", arguments);
                if (dsRequest.operationType == "fetch") {
                    data = isc.addProperties({}, data, { dataex: dsRequest.parentNode.data, sNodeType: dsRequest.parentNode.sNodeType });
                }
                return data;
            }
        });
    
    treeMain = isc.TreeGrid.create({
            ID: "treeMain",
            dataSource: "menu",
            canEdit: true,
            canEditCell: function (rowNum, colNum) {
                return (m_editMode) ? true : this.Super("canEditCell", arguments);
            },
            editByCell: true,
            autoFetchData: true,
            showHeader: false,
            dataArrived: onInitialDataArrived,
            click: onClickNode,
            animateFolders: true,
            showAllRecords: true,
            showOpener: false,
            showConnectors: false
        });
    
    
    var ret = menu.addData({ "id": newId, "parentId": pid, "name": "New Item", "sNodeType": 19, "displayMode": 1, "isFolder": false},
                        function (dsResponse, data, dsRequest) {
                            var i = treeMain.data.findIndex("id", data[0].id);
                            treeMain.startEditing(i, 0, false);
    		});

    TIA,

    Dan

    SmartClient Version: SC_SNAPSHOT-2011-05-27/LGPL Deployment (built 2011-05-27)
    Browser: IE8

    #2
    This code isn't runnable until you provide both the data returned and the missing functions, and this missing code is the actual source of the problem.

    Comment


      #3
      The menu.ashx responds to the add request with...

      {response:{status:0,data:{"parentId":1173,"name":"New Item","sNodeType":"19","isFolder":false,"displayMode":"1","id":1204}}}

      The id (primaryKey) has changed because it is being assigned server-side - might that have something to do with it?

      The menu.addData code is just being called programatically from a Menu.

      Do you also need the server response that populated the TreeGrid initially before the add was actioned?

      Dan

      Comment


        #4
        You can't change primary key on an update. If you need to change the key, issue a remove than an add.

        Comment


          #5
          The primary key is only changed on this add response not on subsequent updates - presumably that is OK as the server is dishing out the primary keys?

          I'm struggling to produce a test case though. Should I be able to put those responses verbatim into .txt files (e.g. "{response:{status:0,data:{"parentId":1173,"name":" New Item","sNodeType":"19","isFolder":false,"displayMo de":"1","id":1204}}}" ) and reference them using fetchDataURL/addDataURL etc?

          TIA

          Dan

          Comment


            #6
            It is allowed to issue an add request with no PK and have a generated PK returned.

            Yes, it works to just put static files at various URLs as faked responses. The samples for RestDataSource actually use this technique.

            Comment


              #7
              I can get a "fetch" request to work with static .txt files but not "add".

              In the RestDataSource I have...

              fetchDataURL: "test_fetch.txt",
              addDataURL: "test_add.txt",

              An "add" POST request is generated but the response status is "405 Method not allowed".

              Full header is...
              HTTP/1.1 405 Method not allowed
              Server: Microsoft-IIS/5.1
              Date: Tue, 05 Jul 2011 09:35:35 GMT
              Connection: close
              Allow: OPTIONS, TRACE, GET, HEAD
              Content-Length: 3923
              Content-Type: text/html

              Is there any way to get this to work? I'm getting tantalizingly close to being able to generate a test case!

              TIA

              Dan

              Comment


                #8
                Looked to be an IIS configuration issue. Following advice at http://www.somacon.com/p126.php I can now service the "add" request.

                Hopefully I'll be able to build a test case now!

                Dan

                Comment


                  #9
                  Test case:

                  Code:
                  <html>
                  <head>
                      <title>Test</title>
                  <SCRIPT>var isomorphicDir="isomorphic/";</SCRIPT>
                      <SCRIPT SRC=isomorphic/system/modules/ISC_Core.js></SCRIPT>
                      <SCRIPT SRC=isomorphic/system/modules/ISC_Foundation.js></SCRIPT>
                      <SCRIPT SRC=isomorphic/system/modules/ISC_Containers.js></SCRIPT>
                      <SCRIPT SRC=isomorphic/system/modules/ISC_Grids.js></SCRIPT>
                      <SCRIPT SRC=isomorphic/system/modules/ISC_Forms.js></SCRIPT>
                      <SCRIPT SRC=isomorphic/system/modules/ISC_DataBinding.js></SCRIPT>
                      <SCRIPT SRC=isomorphic/skins/standard/load_skin.js></SCRIPT>
                  </head>
                  <body>
                  
                  <script>
                  	isc.RestDataSource.create({
                  	    ID: "menu",
                  	    dataFormat: "json",
                  	    nameProperty: "name",
                          fetchDataURL: "test_fetch.txt",
                          addDataURL: "test_add.txt",
                  	    fields: [{
                  	        name: "name",
                  	        title: "Name",
                  	        type: "text",
                  	        canEdit: true,
                  	        required: true
                  	    }, {
                  	        name: "id",
                  	        title: "ID",
                  	        type: "integer",
                  	        primaryKey: true,
                  	        canEdit: false,
                  	        hidden: true,
                  	        required: true
                  	    }, {
                  	        name: "parentId",
                  	        title: "parentId",
                  	        type: "integer",
                  	        canEdit: false,
                  	        hidden: true,
                  	        required: true
                  	    }, {
                  	        name: "isFolder",
                  	        title: "Is Folder",
                  	        type: "boolean",
                  	        canEdit: false,
                  	        hidden: false,
                  	        required: true
                  	    }
                  		]
                  	});
                  
                      treeMain = isc.TreeGrid.create({
                          ID: "treeMain",
                          width: "100%",height: "100%",
                          dataSource: "menu",
                          canEdit: true,
                          canEditCell: function (rowNum, colNum) {
                              return m_editMode;
                          },
                          editByCell: true,
                          autoFetchData: true,
                          showHeader: false,
                          click: onClickNode,
                      	animateFolders: true,
                  		showAllRecords: true,
                  		overflow: "auto",
                      	canReorderRecords: true,
                      	canAcceptDroppedRecords: true,
                      	showOpener: false,
                      	showConnectors: false
                      });
                  
                          isc.Menu.create({
                              ID: "fileMenu",
                              autoDraw: false,
                              showShadow: true,
                              shadowDepth: 10,
                              visibility: "hidden",
                              data: [
                              { title: "Add Folder", keyTitle: "Ctrl+F", click: function () { addNode(0) } },
                              { title: "Add Item", keyTitle: "Ctrl+I", click: function () { addNode(1) } },
                          ]
                          });
                  
                          isc.ToolStripMenuButton.create({
                              ID: "menuButton",
                              title: "File",
                              autoDraw: false,
                              menu: fileMenu
                          });
                  
                          toolStrip = isc.ToolStrip.create({
                              height: "24",
                              width: "100%", 
                              members: [menuButton]
                          });
                  
                      var m_editMode = true;
                  
                      function onClickNode() {
                  
                          node = treeMain.getSelectedRecord();
                  
                          if (m_editMode) {
                              var i = treeMain.data.findIndex("id", node.id);
                              treeMain.startEditing(i, 0, false);
                              return;
                          }
                  
                          if (node.isFolder) {
                              treeMain.toggleFolder(node);
                              return;
                          }
                  
                      }
                  
                      function addNode(nodeType) {
                          var node = treeMain.getSelectedRecord();
                          if (node == null) {
                              node = treeMain.data.getRoot();
                          }
                          else if (!node.isFolder) {
                              node = treeMain.data.findById(node.parentId);
                          }
                          var pid = node.id;
                          var nodeStr;
                          switch (nodeType) {
                              case 0:
                                  {
                                      nodeStr="{ 'id': 0, 'parentId': pid, 'name': 'New Folder', 'sNodeType': 1, 'displayMode': 1, 'isFolder': true}";
                                      break;
                                  }
                              case 1:
                                  {
                                      nodeStr = "{ 'id': 0, 'parentId': pid, 'name': 'New Item', 'sNodeType': 19, 'displayMode': 1, 'isFolder': false }";
                                      break;
                                  }
                          }
                          var ret = menu.addData(eval('(' + nodeStr + ')'),
                                      function (dsResponse, data, dsRequest) {
                                          var i = treeMain.data.findIndex("id", data[0].id);
                                          if (i == -1) {
                                              alert("Couldn't find new id (" + data[0].id + ") in TreeGrid")
                                          }
                                          else {
                                              treeMain.startEditing(i, 0, false);
                                          }
                                      });
                      }
                  </script>
                  </body>
                  </html>
                  If you click on a node it will allow editing but the existing text is cleared. While generating this test case I've found a workaround. If you repeat the field definition for "name" in the treegrid (i.e. fields: [{ name: "name"}]) then it works as expected but from the docs I thought it was enough to have the fields specified in the datasource? Also I wasn't sure why I needed to explicitly code a canEditCell function given that canEdit=true (without the function it won't go into edit mode at all).

                  I have various questions about the behaviour of this test case but my main one now is that if you drag a node or leaf to re-position it no "update" requests are generated. Be careful not to hover over one of the existing folders as the hard-coded fetch will fail for the sub-folder.

                  The isc console shows...
                  16:25:16.293:MUP6:DEBUG:dragDrop:Invoking transferDragData from inside transferNodes - no server queries needed?

                  TIA,

                  Dan
                  Attached Files

                  Comment


                    #10
                    This is a known limitation with auto-detecting editability with the automatically generated fields for a TreeGrid. Just explicitly declaring the "name" field is the only thing you need to do - no canEditCell() override is necessary then.

                    We'll take a look at the drag and drop problem.

                    Comment


                      #11
                      It looks like the drag/drop interaction you describe is a drag-reorder of nodes within the same parent folder (basically within root).
                      In this case no update request is issued since you haven't actually modified the dragged node - it's a reordering of nodes within a folder which isn't automatically associated with a data update type operation.

                      If you drag / drop to a new parent, the intended data change is clear. In this case an update request will be issued with the parent field value modified to reflect the new parent folder.

                      If you do want to have a drag-reorder cause an update to the dropped node (or for the action to be persisted to the server in some other way), you could achieve this via a custom folderDrop handler which directly issued a DataSource request.

                      Comment


                        #12
                        Ah thanks! Getting there now.

                        I've added a folderDrop function and updates to the server are now working. However until I refresh the page the TreeGrid doesn't reflect the result of the drop.

                        Here's my folderDrop function...

                        (menu is the datasource and dispSeq the sequence within the folder)

                        Code:
                        folderDrop: function (nodes, folder, index, sourceWidget)
                                {
                                    var newDispSeq=0;
                                    if (index>0)     
                                    {
                                        newDispSeq=folder.children[index-1].dispSeq+1;
                                    }
                                    else        
                                    {
                                        newDispSeq=folder.children[index].dispSeq;
                                    }
                                    // Shuffle the sequence if needed...
                                    if (index<folder.children.length && folder.children[index].dispSeq>=newDispSeq)
                                    {
                                        var incrementBy=folder.children[index].dispSeq-newDispSeq+1;
                                        for (var i=index;i<folder.children.length;i++)
                                        {
                                            if (folder.children[i].id != nodes[0].id) 
                                            {
                                                folder.children[i].dispSeq += incrementBy;
                                                menu.updateData(folder.children[i]);
                                            }
                                        }
                                    }
                                    nodes[0].parentId = folder.id;
                                    nodes[0].dispSeq=newDispSeq;
                                    menu.updateData(nodes[0]);
                                }
                        If my mistake isn't apparent from this code I can send some requests and responses if that would help.

                        Thanks

                        Dan

                        Comment


                          #13
                          Just changing the indices won't have an effect until you sort.

                          Comment


                            #14
                            Actually I'm not changing the index, just the field which determines the order of items when they are provided by the server.

                            I did try this.sort("dispSeq"); at the end of folderDrop() but it had no effect.

                            However, calling this.Super("folderDrop", arguments) either at the beginning or end of folderDrop() seems to work most of the time so we are definitely getting there!

                            It only fails if the drop is after the last item in a folder. I'll see if I can make a test case for it.

                            Thanks,

                            Dan

                            Comment

                            Working...
                            X