Hybrid View

  1. #1
    Ext User
    Join Date
    Jan 2009
    Location
    Luxembourg
    Posts
    13
    Vote Rating
    0
    ogerardin is on a distinguished road

      0  

    Default [CLOSED] [1.2.3] Bindings not updated when using clear(), reset() or setValue()

    [CLOSED] [1.2.3] Bindings not updated when using clear(), reset() or setValue()


    FieldBindings are great, but they do not always ensure what they should ensure, i.e. that the model properties and field values are always in sync.

    Specifically:
    • calling clear() on the FormPanel clears the fields, but does not update the model
    • calling reset() on the FormPanel resets the fields, but does not update the model
    • calling setValue() on a Field changes the displayed field value, but does not update the model
    I believe that once bindings are in place, you should be assured that your model always reflects changes made to the field, whether programatically or by interacting with the field. Currently only changes made by interacting with the field are reflected into the model.

    Here's a code sample to show what happens.
    • Try typing something into the field, then press "Show model", you will see that the model has been updated. Good
    • Now press "formPanel.clear()". The field is cleared but the model is unchanged. Not good.
    • Same with "formPanel.reset()". The field is reset to its original value, but the model is unchanged. Also not good. On a side note, the field's original value is taken from the field's value when the field is first rendered, not when the field gets bound to a property as one might expect; so if you want reset to actually reset the field to the original model's values, you need to manually call setOriginalValue().
    • Now press "setValue". The field's displayed value is updated, but again the model is unchanged. Again, not good.
    Code:
    package client.testgxtbindings.client;
    
    import com.extjs.gxt.ui.client.binding.FormBinding;
    import com.extjs.gxt.ui.client.data.BaseModel;
    import com.extjs.gxt.ui.client.event.ComponentEvent;
    import com.extjs.gxt.ui.client.event.SelectionListener;
    import com.extjs.gxt.ui.client.widget.button.Button;
    import com.extjs.gxt.ui.client.widget.form.FormPanel;
    import com.extjs.gxt.ui.client.widget.form.TextField;
    import com.google.gwt.core.client.EntryPoint;
    import com.google.gwt.core.client.GWT;
    import com.google.gwt.user.client.ui.RootPanel;
    
    /**
     * Entry point classes define <code>onModuleLoad()</code>.
     */
    public class TestGXTBindings implements EntryPoint {
    
    
        private static class MyModel extends BaseModel {
            public static final String SOME_PROPERTY = "property";
            public String getProperty() {
                return get(SOME_PROPERTY);
            }
            public void setproperty(String value) {
                set(SOME_PROPERTY, value);
            }
        }
    
        /**
         * This is the entry point method.
         */
        public void onModuleLoad() {
            final FormPanel formPanel = new FormPanel();
    
            final TextField<String> textField = new TextField<String>();
            textField.setName(MyModel.SOME_PROPERTY);
            textField.setFieldLabel("Property");
            textField.setValue("original value");
            formPanel.add(textField);
    
            FormBinding formBinding = new FormBinding(formPanel);
            formBinding.autoBind();
    
            final MyModel model = new MyModel();
            model.setproperty("some text");
            formBinding.bind(model);
    
            formPanel.add(new Button("formPanel.clear()") {
                {
                    addSelectionListener(new SelectionListener<ComponentEvent>() {
                        public void componentSelected(ComponentEvent ce) {
                            GWT.log(((Button)ce.component).getText(), null);
                            formPanel.clear();
                            GWT.log("property=" + model.getProperty(), null);
                        }
                    });
                }
            });
    
            formPanel.add(new Button("formPanel.reset()") {
                {
                    addSelectionListener(new SelectionListener<ComponentEvent>() {
                        public void componentSelected(ComponentEvent ce) {
                            GWT.log(((Button)ce.component).getText(), null);
                            formPanel.reset();
                            GWT.log("property=" + model.getProperty(), null);
                        }
                    });
                }
            });
    
            formPanel.add(new Button("textField.setValue(\"qwertz\")") {
                {
                    addSelectionListener(new SelectionListener<ComponentEvent>() {
                        public void componentSelected(ComponentEvent ce) {
                            GWT.log(((Button)ce.component).getText(), null);
                            textField.setValue("qwertz");
                            GWT.log("property=" + model.getProperty(), null);
                        }
                    });
                }
            });
    
            formPanel.add(new Button("Show model") {
                {
                    addSelectionListener(new SelectionListener<ComponentEvent>() {
                        public void componentSelected(ComponentEvent ce) {
                            GWT.log(((Button)ce.component).getText(), null);
                            GWT.log("property=" + model.getProperty(), null);
                        }
                    });
                }
            });
    
    
            RootPanel.get().add(formPanel);
    
    
    
        }
    
    }

  2. #2
    Software Architect
    Join Date
    Sep 2007
    Posts
    13,971
    Vote Rating
    132
    sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light

      0  

    Default


    This is not a bug, this is by design. There was already s thread about that. The problem is that the Change event is not fired in these caes

  3. #3
    Ext User
    Join Date
    Jan 2009
    Location
    Luxembourg
    Posts
    13
    Vote Rating
    0
    ogerardin is on a distinguished road

      0  

    Default


    Could you point me to this thread please? Because I couldn't find it.

    I'm curious to know the reasons behind this design choice that defeats the purpose of FieldBindings altogether. It seems inconsistent to me that in some cases, it is OK to have some fields display a value that differs from the model (except when the field is being edited of course).

  4. #4
    Software Architect
    Join Date
    Sep 2007
    Posts
    13,971
    Vote Rating
    132
    sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light

      0  

    Default


    FieldBinding uses Events.Change of the Field. This event is only fired onblur and only if the value changed.

  5. #5
    Ext User
    Join Date
    Jan 2009
    Location
    Luxembourg
    Posts
    13
    Vote Rating
    0
    ogerardin is on a distinguished road

      0  

    Default


    Quote Originally Posted by sven View Post
    FieldBinding uses Events.Change of the Field. This event is only fired onblur and only if the value changed.
    I'm sorry and I don't mean to rude be but this is not a valid justification; nothing prevents you from firing a ChangeEvent in setValue() if the new value differs from the old one.

    A valid justification would be a use case where you need setValue() NOT TO update the model, and I can't think of any.

    On the contrary, now I have to add a lot of extra code to ensure that when I reset my form, the model is reset too, and when i clear my form, the model is reset too, etc.

    For example, this is the reset() method of my view:
    Code:
    public void reset() {
    
                for (Field f : formPanel.getFields()) {
    
                        Object beforeValue = f.getValue();
                        f.reset();
                        Object afterValue = f.getValue();
    
                        if (afterValue != beforeValue) {
                            if (afterValue != null && afterValue.equals(beforeValue)) {
                                continue;
                            }
                            FieldEvent fieldEvent = new FieldEvent(f);
                            fieldEvent.oldValue = beforeValue;
                            fieldEvent.value = afterValue;
                            f.fireEvent(Events.Change, fieldEvent);
                        }
                }
        }
    Normally instead of this I would expect to be able to call just:

    Code:
        formPanel.reset();

  6. #6
    Software Architect
    Join Date
    Sep 2007
    Posts
    13,971
    Vote Rating
    132
    sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light

      0  

    Default


    We added a configurable option to fire the change event also if you call setValue. Will be in SVN soon.