-
FEATURED COMPONENTS
First time here? Check out the FAQ!
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
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--;
}
}
:-)
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.
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.
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
oke I get the picture, I'll let it sink and think about it.
chillworld ( 2014-09-02 13:15:01 +0800 )editThanks Alecs, have tried that too. Does not work. I must override a custom components method. Will give feedback for the solution.
thanks Stephan
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.
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.
thanks Stephan
PS: will be available in ZKBoost.
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'
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);
}
}
if (!Objects.equals(init, value)&&!(init==null&&StringUtils.isEmpty(value))
chillworld ( 2014-09-03 15:27:31 +0800 )editi 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 )editadditionally 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 )editOK. 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 )editAsked: 2014-09-02 11:54:30 +0800
Seen: 54 times
Last updated: Sep 04 '14
Please help me in form binding
Problem binding values to a composite component
How to access static member field of a class in zul without zscript
How can i load a constant in .zul
MVVM Validator: class not found ? [closed]
MVVM tab box - delay @load until tab pane displayed?
mvvm, load or save with after or before for seach command
how to fire an event when a variable value loaded through VM