Announcement

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

    Custom FormItem and DynamicForm.getValuesAsRecord

    GWT Version: 2.0.3
    Smart GWT Version: 2.2

    I'm trying to create a new custom built FormItem that would load a text file fetched from the server by selecting a file from a drop down (SelectItem) and then populate a text box with the contents of the file. The user would edit the contents in the text box and then when the form is submitted it would read the contents of the text box. I read up a lot and found this post, http://forums.smartclient.com/showthread.php?t=11651, which helped a lot to get me started, but ultimately I've encountered a similar problem to the one mentioned in the linked thread, but in a different form.

    I tried to create a custom DynamicForm that was aware of my new custom FormItem like in the example only to find out that editRecord and saveData are never being called. It was only after digging a bit more in our code that I found that the SmartGWT framework was not being used properly. What is actually happening is that when the submit button is clicked to submit the form someone decided to instead get all the values from the form through getValueAsRecord, package it into a custom component and send it to the server.

    I plan to fix this mistake when I have the time but right now I am already behind schedule so I have no time left. So what I'm begging for is an explanation on how the FormItems are queried when dynamicForm.getValuesAsRecord is called? Does it call FormItem.getValue ? I would have thought so but unfortunately it isn't the case since my log statement is never triggered. Then again maybe I'm doing something wrong with how I coded my custom form. This is the code I used for the custom form.

    Code:
    public class TextLoadingEditorItem extends CanvasItem {
        public TextLoadingEditorItem() {
            setName("TextLoadingEditorItem");
            final DynamicForm dynamicForm = new DynamicForm();
            SelectItem fileSelection = new SelectItem("File");
            TextItem titleArea = new TextItem("File Name");
            TextAreaItem textArea = new TextAreaItem("Editor");
            textArea.setWidth(400);
            textArea.setHeight(800);
            textArea.addChangedHandler(new ChangedHandler() {
                @Override
                public void onChanged(ChangedEvent event) {
                    AlertWindow.post("ChangedHandler called");
                    setValue(event.getValue().toString());
                }
            });
            ButtonItem safeFileButton = new ButtonItem("Save File");
    
            dynamicForm.setItems(fileSelection,
                                            titleArea,
                                            textArea,
                                            saveFileButton);
    
            setShouldSaveValue(true);
            setCanvas(dynamicForm);
        }
    
        @Override
        public void setValue(String value) {
            AlertWindow.post("setValue("+value+")");
            super.setValue(value);
        }
    
    
        @Override
        public Object getValue() {
            AlertWindow.post("getValue(?)");
            return super.getValue(value);
        }
    }
    So to summarize, I create my TextLoadingEditor, insert it into a dynamic form and then when I call getValuesAsRecord the AlertWindow.post("getValue(?)"); never shows up.

    #2
    In a nutshell getValuesAsRecord() does not in general contact FormItems at all, because the FormItems have already notified the form of new values every time there is a change. This is necessary to enable change notifications, detection of whether values have changed, etc.

    In more recent SmartGWT versions there are more docs and samples for CanvasItem that show exactly what to do, as well as a storeValue() API that simplifies the needed code. If you have to stick with your current version, just call dynamicForm.setValue() every time the value is updated.

    Comment


      #3
      Aye, unfortunately we can't upgrade just yet. Our hope in the future is to just burn all the code we have right now, upgrade to the latest GWT and SmartGWT, and start from scratch.

      So I'm a bit confused about which dynamicForm you're talking about. Do you mean (1) the dynamicForm inside of TextLoadingEditorItem? Or (2) the DynamicForm that is using TextLoadingEditorItem?

      Comment


        #4
        2) the DynamicForm that is using TextLoadingEditorItem.

        Comment


          #5
          Things are not working as expected : (

          We started to override the DynamicForm in the following way

          Code:
          public class GWDynamicForm extends DynamicForm {
          
              @Override
              public void setDataSource(DataSource dataSource) {
                  super.setDataSource(dataSource);
                  FormItem[] formItemArray = this.getFields();
                  AlertWindow.post("formItemArray.length = "+formItemArray.length);
                  for(FormItem formItem : formItemArray) {
                      AlertWindow.post("fieldName "+formItem.getFieldName()+ " class " +formItem.getClass());
                      if(formItem instanceof TextLoadingEditorItem) {
                          AlertWindow.post("Modifying TextLoadingEditorItem");
                      }
                  }
              }
          }
          TextLoadingEditorItem is created before the dynamic form in some far off class so we were hoping to pass the DynamicForm to TextLoadingEditorItem during the setDataSource function so that we could link the two classes to do the setValue as you suggested... unfortunately we discovered something VERY strange. The AlertWindow.post("Modifying TextLoadingEditorItem"); never fired off and for the following reasons. If you remember, we modified the dataSource in this thread, http://forums.smartclient.com/showthread.php?t=22430. To do the modification we used DataSourceField.setEditorType. Turns out that even though we modified the editorType, formItem.getClass() in the DynamicForm will still return the original class type. So instead of our formItem being TextLoadingEditorItem it was still TextItem. What are we doing wrong? What can we do to fix this? Also is this approach of what you suggested the wrong way of doing this?
          Last edited by MarkA; 20 Jun 2012, 16:41.

          Comment


            #6
            The docs for setEditorType() explain the special rules for this method and tell you that receiving a generic type is expected, and how to avoid this.

            However there isn't a need for any of this because you can just define an InitHandler for your FormItem and get the form at that time.

            Comment


              #7
              I made a mistake in the code above, which made it hard to understand what we did. I've corrected it now. It was missing the function that we were overriding.

              Form.setInitHandler is not in our version and the rules for setEditorType don't apply in this case since we're trying to differentiate between FormItem types inside of a custom function in a subclass Dynamic form and not inside of a callback handler.

              We're basically at the point now where we have our modified DataSource, we are in the process of creating our DynamicForm and we want to pass a reference of the DynamicForm to our custom FormItem but we can't because we can't tell which item in our DataSource/FormItemArray is TextLoadingEditorItem. There seems to be no getEditorType() in DataSourceField and we can't use instanceof for FormItem : /

              We thought of a few hacks that would solve this problem such as just adding a ChangedHandler to ALL the FormItems in setDataSource, but unfortunately this DynamicForm is VERY dynamic and is used in a lot of places with almost all the basic FormItem types so we can't do anything that would break other Form Items.
              Last edited by MarkA; 20 Jun 2012, 16:43.

              Comment


                #8
                The API is FormItem.addInitHandler(), not Form.setInitHandler(). We're not sure if that was really only added in the past ~2 years (that's how old 2.2 is), but if so, then you really need to just upgrade. There is no point doing development against such an old version when the new version is backwards compatible anyway.

                And the rules for setEditorType() do apply if you call setEditorType() at all.

                Comment

                Working...
                X