I have a GWT page that contains a lot of different fields, which the user needs to fill out. When the user is done filling out the form, they can click on a button on this page, which opens up a PopupPanel with a summary of what they have input. If the user decides all the data they've entered is correct, they have the option of clicking on an "OK" button on this PopupPanel. What I would like to achieve is that when the user clicks on OK, the PopupPanel closes and a method in the initial class (and using the initial class' variables) is triggered. I am unable to use EventBus because of certain restraints.
In my initial class I have this click handler:
buttonAnle.addClickHandler(new ClickHandler()
{
#Override
public void onClick(ClickEvent event)
{
if ( validateTimespan(subs) && validateSubumfeldTimespan(subs) )
{
summary();
}
}
});
The method summary() shows the popuppanel:
private void summary()
{
int subumfelderNr = subs.getRowCount();
int werbeformenNr = kats.getRowCount();
int days = (int) (datumBis.getValue().getTime() - datumVon.getValue().getTime()) / 86400000;
new SubprogramPopup(umfeldText.getTextBoxText(), subumfelderNr - 1, werbeformenNr - 1, days + 1).show();
}
The popup appears, now I need a way for the OK button's click to trigger a method in my initial class. Any help would be greatly appreciated.
One possible solution could be using a interface inside the SubprogramPopup. Add this code to the SubprogramPopup class:
interface MyHandler {
void doSomething();
}
and add MyHandler as another parameter to the constructor of the SubprogramPopup.
SubprogramPopup(Textbox textbox,
int value01,
int value02,
int value03,
MyHandler handler) {}
Now, if you are creating the SubprogramPopup you can use the handler to add something, that should be executed if needed.
new SubprogramPopup(umfeldText.getTextBoxText(),
subumfelderNr - 1,
werbeformenNr - 1,
days + 1,
new MyHandler() {
public void doSomething() {
// enter your code here ...
}
}).show();
Related
My question is how can I get the selected option, if in the SelectionMenuEvent event it doesn't have the method to get the option that the user selected from the menu.
My code:
#Override
public void execute(Member member, Message message) {
val menu = SelectionMenu.create("help.menu");
val command = this.loadAllCommand(message);
command.forEach(c -> menu.addOption(c.getName(), c.getPermission(), c.getDescription(), c.getEmoji()));
message.reply("```Diff\n" +
"+ List of my current commands" +
"\n```").setActionRow(menu.build()).queue();
}
// Event
#Override
public void onSelectionMenu(SelectionMenuEvent event) {
// get selected option of the menu
}
I looked at the SelectionMenuEvent class documentation, let me know if I missed something.
I am using JDA version 4.4.0_350.
You can use SelectMenuInteraction#getValues or SelectMenuInteraction#getSelectedOptions. The event implements this interface.
I am calling java from java-script to close the date picker pop Up using following method.
private native void attachInternal() /*-{+
$wnd.jQuery("div.datePickerDay.datePickerDayIsValue").on( "Click", function() {
this.#com.booxi.admin.client.common.ui.text.DateFormatter::uiDatePickerPopup.hide();
console.log("OK");
});
}-*/;
this method is again called in the method attached.
The problem is that date picker doesn't closes after selecting same date which is already selected, but on value change it closes.I want to close it even after selecting same date as earlier.
The attach method is following
public void attach() {
attachInternal();
datePickerValueChangeRegistration = uiDatePicker.addValueChangeHandler(new ValueChangeHandler<Date>() {
#Override
public void onValueChange(ValueChangeEvent<Date> event) {
uiDatePickerPopup.hide();
uiTextDate.setErrorVisible(false);
uiTextDate.setTextNoFormat(Moment.moment(event.getValue()).format("L"));
}
});
textDateClickRegistration = uiTextDate.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
//if (uiTextDate.isReadOnly())
// return;
if (!uiTextDate.isEnabled())
return;
showPopup();
}
});
It's a bit late, but maybe it helps if anybody has the same problem.
I made the same error. The problem is, the change event only fires if a different value is selected. If the user selects the same value again, then there is no value change, the event does not fire, your code is not executed and the popup does not hide.
You have to use a click event instead of the value change event. Then by every click, even on the old value, the code is executed. But if you just replace the change event with the click event, then the code also is executed when the user clicks on the header of the date picker, for example when he clicks on the arrows to choose a different month. This would brake the functionality of the date picker.
So in the click event you have to check if the click is really in a date cell and not in the header. This can be done with Element.as(event.getNativeEvent().getEventTarget()) and check the element's content, easiest check if the inner text is a date number between 1 and 31.
So the code is like this
uiDatePickerPopup.addDomHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Element target = Element.as(event.getNativeEvent().getEventTarget());
String targetContent = target.getInnerText();
try {
int d = Integer.parseInt(targetContent);
if (d >= 1 && d <= 31) {
uiDatePickerPopup.hide();
...
enter the rest of your code here
...
}
} catch (Exception e) {
/* ignore, click was not on a date cell */
}
}
}, ClickEvent.getType());
(As far as I know there is no more elegant solution. The other possible events are not useful, and you can't restrict the click event only to the date cells, because the getView() method is protected and the underlying CalendarView is final and can't be extended to a subclass providing the necessary check for the content.)
Your JSNI is wrong: you're getting a method reference to the hide() method, but not actually calling it. Also, the this inside the callback is probably the HTML element, and not the class this method pertains to (and finally, click might have to be all lowercase –I don't know jQuery though, so I might be wrong).
It should thus read:
private native void attachInternal() /*-{
var that = this;
$wnd.jQuery("div.datePickerDay.datePickerDayIsValue").on( "click", function() {
that.#com.booxi.admin.client.common.ui.text.DateFormatter::uiDatePickerPopup.hide()();
console.log("OK");
});
}-*/;
I have this behavior added to a component(MarkupContainer)
AjaxSelfUpdatingTimerBehavior updateBehavior = new AjaxSelfUpdatingTimerBehavior(Duration.seconds(3))
{
#Override
public void onEvent(Component component, IEvent<?> event) {
// some business logic
}
};
Somewhere , on the same page I have an AjaxLink which redirects to another page(in whom constructor I pass the actual page as a parameter) and on that page I have a "Back" AjaxLink which redirects me back , calling setResponsePage(myFirstPage) .
The problem is that even though , when rendering the page the behavior updates once , it stops updating once at 3 seconds , as was constructed for.No problem faced with the behavior until leaving the page.
Probably not the best solution , but I managed to fix it by removing the behavior onBeforeRender() of the page and adding again . I declared a field on the page private int autoUpdateBehaviorId = -1;
public void addUpdateBehavior(Component c)
{
if(autoUpdateBehaviorId >= 0)
c.remove(c.getBehaviorById(autoUpdateBehaviorId));
AjaxSelfUpdatingTimerBehavior updateBehavior = new AjaxSelfUpdatingTimerBehavior(Duration.seconds(3))
{
#Override
public void onEvent(Component component, IEvent<?> event) {
// bussines logic
}
};
c.add(updateBehavior);
autoUpdateBehaviorId = c.getBehaviorId(updateBehavior);
}
#Override
protected void onBeforeRender() {
super.onBeforeRender();
addUpdateBehavior(myContainer);
}
Not necessarily the solution to your problem; but I have implemented the behavior by overriding onConfigure method of the AjaxSelfUpdatingTimerBehavior as below.
In my case, I had to update label with a count of current records in queue every 10 seconds.
Following is code snippet:
labelToBeUpdated.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(configurableDelay)) {
#Override
public void onConfigure(Component component) {
String inProgressOutOfTotal = "10/100"; //Business logic to get total count and inprogress count
labelToBeUpdated.setDefaultModel(Model.of(inProgressOutOfTotal));
//Set visibility of the component if needed
}
}
labelToBeUpdated.setOutputMarkupId(true);
Just curious; is it that onEvent is waiting on an event on the component in order to refresh? Since onConfigure is called before the rendering cycle has begun, it is working for me.
But as Sven Meier has mentioned, you might still want to work on his advise to get your code with onEvent.
I am building a simple app and I am implementing it in a simple MVC pattern where the controller adds event handlers to the view. Here's a sample controller code attaching a handler to the UI.
Basically, the code adds an event handler when the UI's save button is clicked. The UI contains the name and id number entry. What I wanted to happen is to pass the name and id number into the actionPerformed function.
ui.onAddStudent(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
System.out.print("test");
}
});
And the receiving function in the UI (in another file) is the following.
public void onAddStudent(ActionListener handler){
//something missing here
addStudent.addActionListener(handler);
}
I am not really into Java because it's not my forte. I actually do JavaScript. Now, a similar handler In JavaScript, one can use the call() or apply() method to call the handler and pass in additional parameters. If the above code was in JS, it would be like
//in the controller
ui.onAddStudent(function(event,id,name){
//I can use id and name
});
//in the UI
ui.onAddStudent = function(handler){
//store into a cache
//add handler to the button
}
//when student is added (button clicked)
handler.call(this,event,id,name);
How do I do the same thing in Java?
You have two choices:
let it as it is, and have the controller get the ID and name from the GUI (and that is the easiest and simplest solution, IMHO)
use your own Event and Listener types, containing this information. For example:
public class StudentAddedEvent {
private long ID;
private String name;
...
}
public interface StudentAddedListener {
void studentAdded(StudentAddedEvent event);
}
The UI would register an ActionListener on the button, and this action listener would do:
#Override
public void actionPerformed(ActionEvent e) {
long id = getIdInGui();
String name = getNameInGui();
StudentAddedEvent event = new StudentAddedEvent(id, name);
for (StudentAddedListener listener : studentAddedListeners) {
listener.studentAdded(event);
}
}
You can define your own Actions too, and set those to the buttons (constructor argument or setAction) and other components.
Extend AbstractAction for that.
I am stuck in getting an absolute position of DialogBox. I know it is the common problem (and strange workaround) for PopupPanel (which is parent to DialogBox) to set it, but what if I want to get it, what is the exact moment when the box attached to DOM? Neither overriding show nor onAttach nor show does not help:
class MyDialog extends DialogBox {
public MyDialog(. . .) {
ComplexPanel vert = new VerticalPanel();
vert.add("Test");
vert.add(new Button("Close", new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
MyDialog.this.hide();
}
}));
setWidget(vert);
this.addAttachHandler(new AttachEvent.Handler() {
#Override
public void onAttachOrDetach(AttachEvent event) {
if (event.isAttached()) Log.debug("attach:"+MyDialog.this.getAbsoluteLeft() +";"+
MyDialog.this.getAbsoluteTop());
}
});
}
#Override
protected void onLoad() {
super.onLoad();
Log.debug("load:"+this.getAbsoluteLeft() +";"+this.getAbsoluteTop());
}
#Override
public void show() {
super.show();
Log.debug("show:"+this.getAbsoluteLeft() +";"+this.getAbsoluteTop());
}
}
So when I call new MyDialog().show();, all this lines do log 0;0, however dialog is positioned in center of a page. But what I want is the sum of the chain of offsetParent positions. (And they are 0 in these moments even in JavaScript, if use JSNI to check this)
Again, setPopupPositionAndShow allows to set position but not get it :(
Finally, I've got this to work:
#Override
public void setPopupPosition(int left, int top) {
super.setPopupPosition(left, top);
if (this.isAttached()) Log.debug("setPos:"+this.getAbsoluteLeft() +";"+this.getAbsoluteTop());
}
It gets the proper position and I hope it is the right way to do it and setPopupPosition is called every time. You will even call it manually when using setPopupPositionAndShow.
I think it will be wise to let this question stay at SO "for future generations".
Upd. If you plan to call center(...) or some similar method of your dialog, be aware that setPopupPosition will be called twice or more times (may be first time with 0, 0), even if you'll check if it isAttached(). Add some additional check to ensure that positions are correct in current call.