Announcement

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

    Problem using CanvasItem to edit values in a ListGrid

    SmartClient Version: v9.0p_2013-11-14/PowerEdition Deployment (built 2013-11-14)

    I have a CanvasItem that is working fine in a DynamicForm, but not in a ListGrid. I'm using a showValueHandler to put the value into the CanvasItem and then calling storeValue() when the value changes.

    I have added logging just before the call to storeValue() and I can see that the correct value is be passed to storeValue, and in fact I can examine the DynamicForm that is created when the grid row is put into edit mode and I can see that the correct new value is in the getValues() map after the call to storeValue. But the new value doesn't show up in the grid row.

    Do I have to call setEditValue() instead of showValue when the CanvasItem is in a grid? If so, how do I detect that it is a grid editor form and get a reference back to the grid row so I can call setEditValue()?

    I've attached my code as a standalone test case which is a modified version of BuiltInDS sample, but it requires the TinyMCE js library. I'm using version 3. I can zip up my version and attach it if needed.
    Attached Files
    Last edited by jay.l.fisher; 19 Feb 2014, 19:14.

    #2
    I was able to find a way to get the grid associated with the CanvasItem, so I changed the TinyMCECanvasItem.updateValue() method to this, which seems to do the trick. If the CanvasItem is in a grid I call setEditValue after calling storeValue.
    Code:
    public static void updateValue(String instanceId, String value) {
    	SC.logDebug("storing value "+value+" for instance "+instanceId);
    	TinyMCECanvasItem instanceItem = instanceMap.get(instanceId);
    	SC.logDebug("instanceItem is "+instanceItem.getName()+" in form "+instanceItem.getForm().getID());
    	instanceItem.setCurrentValue(value==null ? "" : value);
    	instanceItem.storeValue(value); 	
    	try {
     		// The only way I know to tell if the CanvasItem is in a grid is to try to get the grid.
    		ListGrid grid = ListGrid.getOrCreateRef(instanceItem.getAttributeAsJavaScriptObject("grid"));
    		SC.logDebug("Updating grid with value for instanceId "+instanceId);
    		grid.setEditValue(grid.getEditRow(), instanceItem.getName(), value);
    	} catch (Exception e) {
    		SC.logDebug("Exception getting grid for instanceId "+instanceId+" : "+e.getMessage());
    	}
    }
    But surely this is the "right" way to do it. Shouldn't the framework handle the ListGrid update when storeValue is called?

    Comment


      #3
      I found and fixed some other quirks with this implementation and am attaching updated code. I'd still like a response on my last question about storeValue not updating the ListGrid value. But what I have now works.

      There is one other problem I'm still trying to track down. If you run the sample and use the SC console Watch tab you can see what is happening. Double-click on a row in the grid to put it into edit mode. Refresh the Watch tab and you'll see that the ListGrid body now contains a TinyMCECanvas which contains an HTMLFlow as expected.

      But you'll also see two other HTMLFlows that have no parent. The CanvasItem constructor is being called multiple times. Those extra HTMLFlows are created in the FormItemInitHandler which is invoked for each of the CanvasItems.

      Why are there multiple calls to the CanvasItem constructor when one ListGrid row is put into edit mode. And if multiple CanvasItems are created and destroyed for some reason, why aren't their children being destroyed when they are destroyed?

      Here is the sequence of events shown by the SC.logDebug statements I have in various spots.

      15:26:35.160:MUP5:DEBUG:Log:ShowValueEvent is putting record 1 in isc_OID_1
      15:26:35.177:MUP5:DEBUG:Log:unloading isc_OID_1
      15:26:35.284:MUP5:DEBUG:Log:ShowValueEvent is putting record 1 in isc_OID_2
      15:26:35.288:MUP5:DEBUG:Log:ShowValueEvent is putting record 1 in isc_OID_2
      15:26:35.301:MUP5:DEBUG:Log:unloading isc_OID_2
      15:26:35.428:MUP5:DEBUG:Log:ShowValueEvent is putting record 1 in isc_OID_3
      15:26:35.579:MUP5:DEBUG:Log:ShowValueEvent is putting record 1 in isc_OID_3
      15:26:35.647:dblclick7:DEBUG:Log:Initializing element isc_OID_1
      15:26:35.658:dblclick7:DEBUG:Log:Initializing element isc_OID_2
      15:26:35.670:dblclick7:DEBUG:Log:Initializing element isc_OID_3
      15:26:35.715:TMR8:DEBUG:Log:unloading isc_OID_3
      15:26:35.976:TMR8:DEBUG:Log:ShowValueEvent is putting record 1 in isc_OID_4
      15:26:35.989:TMR8:DEBUG:Log:ShowValueEvent is putting record 1 in isc_OID_4
      15:26:36.052:TMR8:DEBUG:Log:ShowValueEvent is putting record 1 in isc_OID_4
      15:26:36.177:TMR3:DEBUG:Log:Initializing element isc_OID_4
      Attached Files

      Comment


        #4
        Isomorphic - I would appreciate some feedback on this. Am I mistaken in thinking that a CanvasItem should "just work" in a ListGrid if it works in a form?

        Comment


          #5
          Hi Jay
          We've been looking at your example code to see what's going on. The short answer is no, you shouldn't need to do anything special to use a CanvasItem custom editor in a ListGrid.

          The reason the values weren't being saved is that when a grid goes into edit mode it checks whether the field being edited will have an item which can receive keyboard focus (canFocus true).
          For a custom CanvasItem the system has to rely on the developer marking the item as canFocus true as it will depend on the Canvas being embedded in the item.
          You can therefore resolve this issue by explicitly calling 'setCanFocus(true)' on your TinyMCECanvasItem as part of setupEditor().

          We'll look into the issue with additional items being created (and possibly destroyed) and follow up again.

          Regards
          Isomorphic Software

          Comment


            #6
            We're not seeing the orphaned HTMLFlows you describe if we run your original code (from the first post), with the change to "setCanEdit(true)" for TinyMCECanvasItems.

            We think that the changes you made to get this working (as posted with your second set of code) are responsible for these orphaned items.
            There are a number of changes and we haven't analyzed exactly what the differences are / why this would cause additional things to get created and whether it is indicative of a framework bug rather than problems in the logic for these classes. Before we dig into this, could you see if the "setCanEdit()" fix will actually get things working for you, without these odd orphaned HTMLFlows showing up? We'd rather not sink time into investigating what may become an unused codepath.

            Thanks
            Isomorphic Software

            Comment


              #7
              Adding canFocus(true) solves the storeValue issue.
              Adding canEdit(true) solves the orphaned HTMLFlows.

              Is there any way for a blur handler to get called when focus moves away from the canvas? I'm looking for a common point at which to unload the editor's value back into the FormItem value in time for it to be picked up by the framework.

              I'm currently using TinyMCE's change callback but it doesn't get called if the user just stops typing and clicks away from the grid row causing the editors for the row to disappear. So I'm looking for some event where I have an opportunity to storeValue one last time. The Canvas's destroy() method doesn't seem to be called when the row ends editing.
              Last edited by jay.l.fisher; 21 Feb 2014, 11:56.

              Comment


                #8
                You can probably use the listGrid EditorExitHandler to achieve this. That should be fired when the user clicks outside the editor to dismiss it, giving you a chance to store out the value to the formItem.

                As an aside, another option for this might be to have your canvasItem show a button which pops up a modal window containg the TinyMCE editor. Obviously that's a fundamentally different UI, but we bring it up in case you haven't considered this, as it would give you more freedom about how to display the editor to the user (not constrained by fitting such a large component into a ListGrid body), and more control over when to "dismiss" the editor.

                Regards
                Isomorphic Software

                Comment


                  #9
                  I've tried both a grid.events.EditorExitHandler and a form.fields.events.EditorExitHandler on the CanvasItem and neither of them gets fired.

                  I know poping up a window with the editor in a form would give more control, but in this case direct editing in a grid is preferable. I'm also trying to use this as a pattern we can follow for other CanvasItems that won't' have as complex a UI but would need to plug into both forms and grids.

                  Comment


                    #10
                    We're not seeing a problem with the editorExitHandler failing to fire.
                    We tweaked the grid definition to add an editorExitHandler:
                    Code:
                    		ListGrid grid = new ListGrid();
                    		
                    		grid.setDataSource(getGridDS());
                    		grid.setData(getGridData());
                    		grid.setAutoFitData(Autofit.BOTH);
                    		grid.setCanEdit(true);
                    		grid.setSaveLocally(true);
                    		
                    		grid.addEditorExitHandler(new EditorExitHandler() {
                    			
                    			@Override
                    			public void onEditorExit(EditorExitEvent event) {
                    				SC.logWarn("*********************************");
                    				
                    			}
                    		});
                    Our steps were to double click in the second field, make some changes to the text within the rich text editor, then click outside the grid to dismiss the editor. For us, the logs show the "*****..." as expected.

                    Comment


                      #11
                      Nevermind. I found a way to implement a blur event handler in the TinyMCE component itself and solved the problem that way. Thanks!

                      Comment


                        #12
                        Originally posted by Isomorphic View Post
                        We're not seeing a problem with the editorExitHandler failing to fire.
                        I think the difference is that I tried adding the EditorExit handler to the CanvasItem and the ListGridField, not the grid itself.

                        Comment

                        Working...
                        X