1

How to catch the form status (isDirty) in code? [closed]

asked 2014-09-02 11:54:30 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2014-09-02 11:55:49 +0800

Hi all,

i'm stumbled about how to catch the form status in code. There's no possibility to add an eventlistener to SimpleForm.

i can react in zul code of the form status by showing an animated icon. But i will place this icon in the tab header which is created by code. So i will send a global command to it if the state is changed. Any ideas how to catch if the status is changed?

thanks Stephan

delete flag offensive retag edit

The question has been closed for the following reason "the question is answered, right answer was accepted" by terrytornado
close date 2014-09-04 16:12:46

10 Answers

Sort by ยป oldest newest most voted
1

answered 2014-09-03 15:44:09 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2014-09-04 09:40:12 +0800

:-)

I have one line more:

    if (!Objects.equals(init, value)) { // different from original
        if (value instanceof String) { // check for String
            if (init == null && StringUtils.isEmpty((String) value)) {
                _dirtyFieldNames.remove(field);
                return;
            }
        }
        _dirtyFieldNames.add(field);
    } else {
        _dirtyFieldNames.remove(field);
    }

Edit: Check for String is needed.

So we cannot override the internal private variables we have copied the complete class FormImpl.java to an equal named package named org.zkoss.bind.impl in our project. Than making the modifications. This equal named class is prefered called by java because this class is searched at first in the project files.

link publish delete flag offensive edit
0

answered 2014-09-03 14:54:46 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2014-09-03 14:59:47 +0800

Thanks Chill,

seems it's a problem in the FormImpl class. If a binded component have an intial value of NULL and we insert a few signs, jump to next field to evaluate the changes and than remove the inserted signs back than the state is dirty. because the setField method evaluate the origin value 'NULL' is not '' (empty). That's right but not in our sense. In the UI it looks equal if a textbox value is NULL or empty.

public class FormImpl implements Form,FormExt,Serializable {
...
public void setField(String field, Object value) {
        _fields.put(field, value);
        final Object init = _initFields.get(field);
        if (!Objects.equals(init, value)) { //different from original
            _dirtyFieldNames.add(field);
        } else {
            _dirtyFieldNames.remove(field);
        }
    }
link publish delete flag offensive edit

Comments

if (!Objects.equals(init, value)&&!(init==null&&StringUtils.isEmpty(value))

chillworld ( 2014-09-03 15:27:31 +0800 )edit
1

i created a fiddle example that listens to a PropertyChangeEvent to react on dirty changes (http://zkfiddle.org/sample/34fnnge/1-form-dirty-listener) ... to me the status looks consistent to what will happen when the form is saved, a null value overridden with an empty string is "dirty" to me

cor3000 ( 2014-09-04 07:23:00 +0800 )edit

additionally I'd not try to hide the information that something changes, even if invisible to the user. the DB will handle null values different to empty strings. If you don't want that: initialize string fields with empty string, and the form will behave as you expect - reverting dirty on clearing.

cor3000 ( 2014-09-04 07:26:16 +0800 )edit

OK. The solution from top does only prevent that the (NULL != "" ) is storing in the dirtyFields list. But the value in the textbox is changed from null to empty string. So it's right to let the origin code untouched. In my case i now initialize the hibernate pojos with an empty String.

terrytornado ( 2014-09-04 16:10:03 +0800 )edit
1

answered 2014-09-03 12:33:26 +0800

chillworld gravatar image chillworld flag of Belgium
5337 4 9
https://github.com/chillw...
public class NotifiableSimpleForm extends FormImpl { 

    private initCount = 0;

    public OXNotifiableSimpleForm() {
        super();
    }

    @Override
    public void addSaveFieldName(String fieldName) {
        super(fieldName);
        initCount++;
    }

    @Override
    public void setField(String field, Object value) {
        super.setField(field, value);

    if (initCount > 0) {
        if (isDirty()) {
            // Do what you have to do

            System.out.println("isDirty");
         } else {
             // The other case
             System.out.println("is not Dirty");
         }
    } else {
        initCount--;
    }
}
link publish delete flag offensive edit
0

answered 2014-09-03 12:22:25 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

I have re-opened this task because the solution works not really well. If i have several tabs with 'form' content in it it does not switch back the isDirty state if i make the changes back. The status is already 'isDirty = true'

link publish delete flag offensive edit
0

answered 2014-09-02 17:40:29 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2014-09-02 17:49:11 +0800

Hmmm, interesting Chill.

At time i have a solution with a custom component where i override the setValue()

<!-- ### show animation in tab if data are changed ### -->
<ox_propChangeToGlobCmd visible="false" value="@load(fxStatus.dirty)" 
                    componentId="@load(vm.tab.id)" />

So the Tabs are created in code i have no ViewModel for it and cannot use @GlobalCommand. I have implemented an EventQueue in my customized Tab class which are triggered from the setValue() in the ox_propChangeToGlobCmd component. In that case seems i'm a little bit more flexible because i can overhand the component ID too.

image description

thanks Stephan

PS: will be available in ZKBoost.

link publish delete flag offensive edit
0

answered 2014-09-02 15:46:24 +0800

chillworld gravatar image chillworld flag of Belgium
5337 4 9
https://github.com/chillw...

updated 2014-09-02 15:47:52 +0800

Stephan, what about a custom simpleform?

public class NotifiableSimpleForm extends FormImpl {

    @Override
    public void setField(String field, Object value) {
        super(field,value);
        if (isDirty()) {
            //Do what you have to do
        } else {
            //The other case
        }
    }
}

Greetz chill.

link publish delete flag offensive edit
0

answered 2014-09-02 15:01:11 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

Thanks Alecs, have tried that too. Does not work. I must override a custom components method. Will give feedback for the solution.

thanks Stephan

link publish delete flag offensive edit
0

answered 2014-09-02 14:43:34 +0800

Alecs gravatar image Alecs
103 5

I don't know if it's your case, but have you tried with instant="true" in your input elements? Take a look at the docs

link publish delete flag offensive edit
0

answered 2014-09-02 12:54:58 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2014-09-02 12:57:13 +0800

Hi chill,

thanks. But that's not want i want. At time the ZK Binder reacts immediately if i jump to the next field and the icon is showed and animated. In your sample it does it after calling the save method.

I will try a hack with a custom label in which i will override the setValue method by calling additionally the BindUtils.postGlobalCommand method. Because the onChange event i.e. in textbox is only fired if the user makes changes in the fontend self.

<textbox visible="false" value="@load(fxStatus.dirty)" onchange="@command('onFormStatusChanged')"/>

thanks Stephan

link publish delete flag offensive edit

Comments

oke I get the picture, I'll let it sink and think about it.

chillworld ( 2014-09-02 13:15:01 +0800 )edit
0

answered 2014-09-02 12:19:25 +0800

chillworld gravatar image chillworld flag of Belgium
5337 4 9
https://github.com/chillw...

Hey Stephan,

You could pass the simpleform in the command like this :

@Command('save',form = fx)

In the java :

@Command
public void save (@BindingParam("form") SimpleForm form) {
    boolean dirty = form.isDirty(); 
}

Greetz chill.

link publish delete flag offensive edit

Comments

for global command dis the same tactic.

chillworld ( 2014-09-02 12:20:11 +0800 )edit

Question tools

Follow
2 followers

RSS

Stats

Asked: 2014-09-02 11:54:30 +0800

Seen: 52 times

Last updated: Sep 04 '14

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More