zk: after confirmation box, page refresh issue, binder not working - java

I was successfully deleting selected items from listbox and after that all objects were deleted from db and listbox was refreshed.
then i added the confirmation box with yes and no option, then my list wasn't refreshed. i saw this thread with similar problem on zk forum with a solution, i implemented it but getting the class cast exception
I am using MVVM
http://forum.zkoss.org/question/73640/refreshing-listbox-after-deleting-an-itemrow/
code getting the exception:
AnnotateDataBinder binder = (AnnotateDataBinder) userWin.getAttribute("binder");
binder.loadAll();
exception:
Mar 21, 2013 5:22:23 PM org.zkoss.zk.ui.impl.UiEngineImpl handleError:1352
SEVERE: >>java.lang.ClassCastException: org.zkoss.bind.AnnotateBinder cannot be cast to org.zkoss.zkplus.databind.AnnotateDataBinder
looking forward to hear from you. I have searched the net, but couldn't find anything but updating the zk. i am already using the latest version of zk 6.5.1.1.
thanks in advance.
#after adding your suggested line of code, my list was not updated, here is my method
#Override
#Command("deleteAllSelected")
#NotifyChange({"selectedObject","objectList"})
public void deleteAllSelected() {
logger.info("in deleteAllSelected()>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
logger.info("direct selection: " + objectList.getSelection());
final Set<UserIntelliopsDTO> setMe = objectList.getSelection();
logger.info("selectedion size in dellete all" + setMe.size());
EventListener<ClickEvent> clickListener = new EventListener<Messagebox.ClickEvent>() {
public void onEvent(ClickEvent event) throws Exception {
if (Messagebox.Button.YES.equals(event.getButton())) {
int i =0;
for(UserIntelliopsDTO dto:setMe){
userService.deleteUserIntelliops(dto.getUserIntelliOps().getUserId());
logger.info("siapa:userIntelliops " + dto.getUserIntelliOps() + dto.getUserIntelliOps().getUserId());
selectedObject = null;
logger.info("iteration: " + i);
++i;
}
selectedObject = null;
deleteAllSelectedButton.setVisible(false);
enableEditMode(true);
}
}
};
Messagebox.show("Are you sure you want to delete all selected records?", "Delete All Selected",
new Messagebox.Button[] { Messagebox.Button.YES,
Messagebox.Button.NO }, Messagebox.QUESTION,
clickListener);
BindUtils.postNotifyChange(null, null, this, "*");
}

I am assuming you are using MVVM Model..So you can do this thing when you will click on delete button below method will code...
#Command
public void doDeleteItems(#ContextParam(ContextType.VIEW) Component view) {
logger.debug("Delete Icon selected");
if (myModel.getSelectedListItem() == null || myModel.getSelectedListItem().isEmpty()) {
showError("No rows are selected");
} else {
Messagebox.show("Are you sure you want to delete?", "Alert !!", Messagebox.YES | Messagebox.NO, Messagebox.QUESTION,new org.zkoss.zk.ui.event.EventListener() {
public void onEvent(Event evt) throws InterruptedException {
if (evt.getName().equals("onYes")) {
//Add code for Deletion
if (listModel.contains(deletedObj))
listModel.remove(deletedObj);
}
else{
//Do somthing else
}
BindUtils.postNotifyChange(null, null, this, "*");//this means current viewmodel object and refresh the variables
}
As i did BindUtils.postNotifyChange() it will do magic for you refreshing the list or you can use NotifyChange("*")
One more thing you have to do here remove object from list after deleting the record...

Related

Getting unwanted popup "You have not saved your changes. If you close this flow, then your changes will be lost. Do you want to continue?"

Getting this popup every time whenever calling a bean method via valueChangeListener property from SelectOneChoice in a jsff page.
I need help to block this unwanted popup.
SelectOneChoice's property of the .jsff page:
<af:selectOneChoice value="................."
label=".................."
required="..............."
shortDesc=".............."
id="....................."
valueChangeListener="#{TransferWorkAreaBean.onBookLovChange}"
autoSubmit="true">
<f:selectItems value="............" id="si2"/>
<f:validator binding="......."/>
</af:selectOneChoice>
Method in Bean Class::
public void onBookLovChange(ValueChangeEvent valueChangeEvent) {
valueChangeEvent.getComponent().processUpdates(FacesContext.getCurrentInstance());
invokeELMethod("#{bindings.methodToExecute.execute}", new Class[0], new Object[0]);
AdfFacesContext.getCurrentInstance().addPartialTarget(getBusinessTable());
}
Method details of binding Method::
public void executeInvetoryQueryOnBookChange(String btg) {
OAViewObjectImpl vo = getBusinessOverview();
VariableValueManager vvm = vo.ensureVariableManager();
vvm.setVariableValue("bindBookTypeCode", btg);
vo.executeQuery();
}
Please note, in some places I have used encrypted data for policy.
Please also note, that the uncommittedDataWarning property is not ENABLED.
This popup only appear when the option uncommittedDataWarning is set to "on" at the root af:document tag. Try to run a full search in your JDevelopper for "uncommittedDataWarning".
Another way of avoiding this popup in this specific case would be to ensure that your data are committed or rollback in your data model. As the popup only appear if some data aren't committed when a user navigate outside the af:document. You could run something like so right before your
invokeELMethod("#{bindings.methodToExecute.execute}", new Class[0], new Object[0]);
How to commit if needed (https://cedricleruth.com/how-to-programmatically-commit-or-rollback-a-transaction-in-oracle-adf/)
private void commitIfDirty() {
try {
ViewObject vo = this.getViewObjectFromIterator("YOUR_ITERATOR_NAME");
boolean isNotSaved = vo.getApplicationModule()
.getTransaction()
.isDirty();
if (isNotSaved) {
vo.getApplicationModule()
.getTransaction()
.validate();
vo.getApplicationModule()
.getTransaction()
.commit();
}
} catch (ValidationException validationException) {
//log it and warn the user that his data isn't valid
} catch (Exception error) {
//log it and warn the user something went wrong
}
}
private ViewObjectImpl getViewObjectFromIterator(String nomIterator) {
ViewObjectImpl returnVO = null;
DCBindingContainer dcb = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
if (dcb != null) {
DCIteratorBinding iter = dcb.findIteratorBinding(nomIterator);
if (iter != null) {
returnVO = (ViewObjectImpl)iter.getViewObject();
}
}
return returnVO;
}

Getting LiveData inside the Repository class and update the Data inside the Database without an endless loop

I'm trying to create an app that only adds an entry to the database if there is no entry already at a specific time intervals and modifies the existing entry if there is already one in the database. I'm using Room.
It works, but only with a workaroud, because I have to call the add function twice before the value gets added (make the input two times before it works). And I also don't like my adding the Observer and immediately removing it afterwards. I also had to implement the workaround when instatiating the DB, with a value when it was first created.
How can I get the data from my LiveData List inside the Repository class and change it without ending up in an endless loop or how do I have to redesign my code to avoid that?
The complete code can be found on my Github account: Github repository
I would really appreciate any suggestion fix my problem and learn to design and plan my code better.
MainActivity
public void ok_clicked(View view) {
Intent intent = new Intent(this, DataActivity.class);
...
Diary addDiary = new Diary(new Date(), diaryCh.isChecked(), readingCh.isChecked(),writingCh.isChecked(),pianoCh.isChecked(),youtubeCh.isChecked());
mDiaryViewModel.insert(addDiary);
startActivity(intent);
}
DiaryViewModel
public void insert(Diary diary) {mRepositroy.add(diary);}
DiaryRepository
public class DiaryRepository {
private DiaryDao mDiaryDao;
private LiveData<List<Diary>> mEntriesToday;
DiaryRepository(Application application) {
AppDatabase db = AppDatabase.getDatabase(application);
mDiaryDao = db.diaryDao();
mEntriesToday = mDiaryDao.findEntriesByDate(Dates.getYesterdayMidnight(), Dates.getTomdayMidnight());
}
LiveData<List<Diary>> getmEntriesToday() { return mEntriesToday;}
void add(Diary diary) {
Observer<List<Diary>> observerEntriesToday = new Observer<List<Diary>>() {
#Override
public void onChanged(List<Diary> diaries) {
if (diaries != null) {
Log.e(TAG, "add: with matching entries"+ diaries.get(0) + " add: " + diary );
diaries.get(0).addAttributes(diary);
new updateDiaryAsyncTask(mDiaryDao).execute(diaries.get(0));
} else {
Log.e(TAG, "add: without matching entries"+" add: " + diary );
new insertDiaryAsyncTask(mDiaryDao).execute(diary);
}
}
};
getmEntriesToday().observeForever(observerEntriesToday);
getmEntriesToday().removeObserver(observerEntriesToday);
}
You shouldn't be using LiveData in this scenario at all. It is only a wrapper for data that will be observed from Activity/Fragment.
First you need to modify mEntriesToday to be MutableLiveData so you can update it.
In your case, you can omit using Observer for updating DB, and so something simple like:
void add(Diary diary){
if (mEntriesToday.getValue() != null) {
Log.e(TAG, "add: with matching entries"+ mEntriesToday.getValue().get(0) + " add: " + diary );
mEntriesToday.getValue().get(0).addAttributes(diary);
new updateDiaryAsyncTask(mDiaryDao).execute(mEntriesToday.getValue().get(0));
} else {
Log.e(TAG, "add: without matching entries"+" add: " + diary );
new insertDiaryAsyncTask(mDiaryDao).execute(diary);
}
}
If you need this data, outside this class, then you can use getmEntriesToday() and observe it.
You can get the value of the LiveData using the getValue() method
void add(Diary diary) {
List<Diary> diaries = mEntriesToday.getValue();
if(diaries!=null){
diaries.get(0).addAttributes(diary);
//update
}else{
//insert
}

Sending Textfield input on ButtonClick or Enter Key

I'm trying to make a Chat, so that when I press enter or press the 'Send' Button, the input of the Textfield will go into a ListView. And it does it's job, although the code is really messy.
My controller code is as following:
public void initialize() {
sendButton.setDisable(true);
}
public void isChatEmpty() {
boolean isChatEmpty = textInput.getText().isEmpty();
sendButton.setDisable(isChatEmpty);
}
public void sendMessageOnClick(){
sendButton.setOnAction((e) -> {
String message = textInput.getText();
chatHistory.getItems().add("Sorin: " + message + "\n");
textInput.setText(null);
sendButton.setDisable(true);
});
}
public void sendMessageOnEnter(){
textInput.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.ENTER) {
String message = textInput.getText();
chatHistory.getItems().add("Sorin: " + message + "\n");
textInput.setText(null);
sendButton.setDisable(true);
System.out.print("test");
}
});
}
I know it works because I can see it in the GUI, but I somehow, get a Nullpointer on my 'isChatEmpty', which to be fair, I do not know why.
Caused by: java.lang.NullPointerException
at sample.Controller.isChatEmpty(Controller.java:29)
Also, is there a way to combine the two Lambdas functions?
Thank you in advance!
In case of enter and click there is an easy way to deal with this: Use the onAction method for both. For TextField this is triggered when you press enter. Furthermore those handlers should be assigned from fxml. Also use binding to disable the button:
<TextField fx:id="textInput" onAction="#send"/>
<Button fx:id="sendButton" text="Send" onAction="#send"/>
#FXML
private void initialize() {
sendButton.disableProperty().bind(textInput.textProperty().isEmpty());
}
#FXML
private void send() {
String message = textInput.getText();
if (message != null && !message.isEmpty()) {
chatHistory.getItems().add("Sorin: " + message);
textInput.clear();
}
}
In isChatEmpty() method the result of textInput.getText() is null as you set it with textInput.setText(null);.
This null causes NPE (see docs for String.isEmpty()).
To resolve this you can remove isChatEmpty() method and setup unidirectional binding:
public void initialize() {
sendButton.disableProperty().bind(textInput.textProperty().isEmpty());
}
Note the .isEmpty() here is not a call to String.isEmpty() but to
StringExpression.isEmpty() what generates binding of type BooleanBinding.

Tapestry5 zone doesn't update on radio button change using zoneUpdater

I've got 2 radio buttons on my Tapestry5 page and I want to update zone when value changes:
<t:radio t:id="allDay" t:mixins="zoneUpdater" t:event="allDayChanged" t:clientEvent="change" zone="timeRecZone"/>
<t:radio t:id="timeRestricted" t:mixins="zoneUpdater" t:event="timeRestrictedChanged" t:clientEvent="change" zone="timeRecZone"/>
<t:zone t:update="show" elementName="div" t:id="timeRecZone" id="timeRecZone">
<t:if test="timeRestrictedSelected">
.
.
.
I'm using known zoneUpdater mixin which works fine for me with textfield at other place of my page. But here, I don't really see timeRecZone get updated, because area under the IF condition is not being shown and I don't see following statement being logged when I'm clicking radios.
public boolean isTimeRestrictedSelected() {
log.info("***** isTimeRestrictedSelected...");
return selectedTimeRestriction == TimeRestriction.TIME_RESTRICTED;
}
This part (change event) works though:
public void onAllDayChanged() {
selectedTimeRestriction = TimeRestriction.ALL_DAY;
log.info("***** allDayChanged called: " + selectedTimeRestriction);
}
public void onTimeRestrictedChanged() {
selectedTimeRestriction = TimeRestriction.TIME_RESTRICTED;
log.info("***** timeRestrictedChanged called: " + selectedTimeRestriction);
}
Has anybody experienced this while working with radio/zone update? Many thanks.
Mea culpa, solution is here:
public void onAllDayChanged() {
selectedTimeRestriction = TimeRestriction.ALL_DAY;
ajaxResponseRenderer.addRender("timeRecZone", timeRecZone);
}
public void onTimeRestrictedChanged() {
selectedTimeRestriction = TimeRestriction.TIME_RESTRICTED;
ajaxResponseRenderer.addRender("timeRecZone", timeRecZone);
}

Disable back button in GWT

Is there a way to disable the Back button in a browser (basically clearing the History token stack) in GWT? Once I browse to a certain page in my application I want to make sure that the user can't use the back button to go back, but only be able to use links on the page to navigate the site.
You cannot disable a button just intercept it and change its return to something the browser does not understand.
This removes the history:
Window.addWindowClosingHandler(new ClosingHandler() {
#Override
public void onWindowClosing(ClosingEvent event) {
event.setMessage("My program");
}
});
To understand it see: http://groups.google.com/group/google-web-toolkit/browse_thread/thread/8b2a7ddad5a47af8/154ec7934eb6be42?lnk=gst&q=disable+back+button#154ec7934eb6be42
However, I would recommend not doing this because your it goes against good UI practices. Instead you should figure out a way that the back button does not cause a problem with your code.
Call the method below in the onModuleLoad().
private void setupHistory() {
final String initToken = History.getToken();
if (initToken.length() == 0) {
History.newItem("main");
}
// Add history listener
HandlerRegistration historyHandlerRegistration = History.addValueChangeHandler(new ValueChangeHandler() {
#Override
public void onValueChange(ValueChangeEvent event) {
String token = event.getValue();
if (initToken.equals(token)) {
History.newItem(initToken);
}
}
});
// Now that we've setup our listener, fire the initial history state.
History.fireCurrentHistoryState();
Window.addWindowClosingHandler(new ClosingHandler() {
boolean reloading = false;
#Override
public void onWindowClosing(ClosingEvent event) {
if (!reloading) {
String userAgent = Window.Navigator.getUserAgent();
if (userAgent.contains("MSIE")) {
if (!Window.confirm("Do you really want to exit?")) {
reloading = true;
Window.Location.reload(); // For IE
}
}
else {
event.setMessage("My App"); // For other browser
}
}
}
});
}
I found a way to make GWT ignore the back-button: Just add historyitem x if no historyitem was set and do nothing on x.
set a historyitem on startup
History.newItem("x")
in the ValueChangeHandler of History add the following:
String historyToken = event.getValue();
if (!historyToken.equals("x"))
History.newItem("x");
Window.addWindowClosingHandler(new ClosingHandler() {
#Override
public void onWindowClosing(ClosingEvent event) {
event.setMessage("My program");
}
});
That is not a fool proof solution. In fire fox I can press the back button and the onWindowClosing method is never invoked. The reason is that I have used History.newItem() and since history exists the back button or backspace buttons simply navigate through the browser history.
So....fix that :)
Put this in your index.html file:
window.open('html page(For example trial.html)', 'Name of the desired site', width='whatever you want',height='whatever you want', centerscreen=yes, menubar=no,toolbar=no,location=no,
personalbar=no, directories=no,status=no, resizable=yes, dependent=no, titlebar=no,dialog=no');

Categories

Resources