Datepicker don't closes after picking same date GWT - java

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");
});
}-*/;

Related

Trigger GWT class' method from inside other class

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();

How to respond to click on a table row in vaadin

I've got the following code:
public Button getBtnSubmit(com.vaadin.ui.Button.ClickListener l) {
if (null != l) {
btnSubmit.addListener(l);
}
return btnSubmit;
}
public Table getTableCompany(HeaderClickListener hl) {
if (null != hl) {
tableCompany.addListener(hl);
}
return tableCompany;
}
I would like to add a listener that fires when I select a (different) row in the table.
This so that I can refresh some other controls with the table data, which listener should I use?
addListener is deprecated now. Use the following instead.
table.addItemClickListener(new ItemClickEvent.ItemClickListener() {
#Override
public void itemClick(ItemClickEvent itemClickEvent) {
System.out.println(itemClickEvent.getItemId().toString());
}
});
I would go for ItemClickListener:
table.addListener(new ItemClickEvent.ItemClickListener() {
#Override
public void itemClick(ItemClickEvent event) {
//implement your logic here
}
});
edit: For Vaadin 7+, use addItemClickListener method instead of addListener.
You want to add a ValueChangeListener
If you use the ValueChangeListener don't forget to set
table.setImmediate(true);
This means that the browser will report a change on selection immediately. If you don't set this your listener is not called.
Read https://vaadin.com/book/-/page/components.table.html, section 5.15.1 "Selecting Items in a Table". You want to add a Property.ValueChangeListener.
Many of these answers are both correct, and incorrect.
If you need to get the selected items in response to the click, register a ValueChangeListener. Calling getValue() to retrieve the selection from the ItemClickListener might be 1 item behind in a MultiSelect list. For example, the set of items won't include/exclude the item triggering the callback. You will not have a reference to the clicked item however.
If you simply want to respond to a click on an item, and do not need to consider the current selection state, register an ItemClickListener instead. This way you will know what item was actually clicked.

GWT equivalent of jQuery change() for form elements

Can anyone tell me whether there is an equivalent method in GWT like change in jQuery for form elements like radio-buttons, checkboxes, etc, which is fired the moment any such button is checked or unchecked? If so, how do I use it? I found a method like addValueChangeHandler in the Google docs, but apart from providing the prototype, there is no working example.
Specifically, if I want a handler which will wait for a checkbox being checked or unchecked, and accordingly pop up an alert like A checkbox has been checked!!, along with that buttons accompanying text.
CheckBox newOption = new CheckBox();
newOption.setText("Check to see alert");
newOption.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
#Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
if (event.getValue()) {
Window.alert("Checkbox is checked!");
} else {
Window.alert("Checkbox is unchecked!");
}
}
});

Get GWT DialogBox absolute position - onLoad/onAttach/show do not helps

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.

Getting ENTER to work with a JSpinner the way it does with a JTextField

First, to make my job explaining a bit easier, here's some of my code:
JSpinner spin = new JSpinner();
JFormattedTextField text = getTextField(spin);
text.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
// Do stuff...
}
});
...
private JFormattedTextField getTextField(JSpinner spinner) {
JComponent editor = spinner.getEditor();
if (editor instanceof JSpinner.DefaultEditor) {
return ((JSpinner.DefaultEditor )editor).getTextField();
} else {
System.err.println( "Unexpected editor type: "
+ spinner.getEditor().getClass()
+ " isn't a descendant of DefaultEditor" );
return null;
}
}
So as you can see, I got that far. And indeed, when I type in a value into the text field component of the spinner (JFormattedTextField), and THEN press ENTER, it works.
What I want now is to be able to have the text field respond to ENTER without having to manually type in a new value (which sorta defeats the purpose of making a spinner out of it). How do I do that?
I know this is not the action listener...but maybe this can work for you?
text.addKeyListener( new KeyAdapter() {
#Override
public void keyReleased( final KeyEvent e ) {
if ( e.getKeyCode() == KeyEvent.VK_ENTER ) {
System.out.println( "enter pressed" );
}
}
} );
I just ran into an issue relating to this, myself. In my case, I had a JSpinner with a SpinnerNumberModel setup so I could input numerical ID values, and then retrieve them from a remote database. This worked all well and good with a JButton as my trigger for the query, but I wanted to be able to switch focus to the field via Tab, and hit enter, and also be able to change the value by entering an ID with numerical keys, then hit enter.
The one that was giving me the most issues was manually entering the ID with numerical keys, then pressing enter. When I would do this, the query would still happen, but it was querying the previous ID rather than the one I just entered, so I'd have to hit enter again to query the new ID (see code)
((JSpinner.DefaultEditor) minRng.getEditor()).getTextField().addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
queryData();
}
}
});
and the query method:
private void queryData() {
int minVal = Integer.parseInt(minRng.getValue().toString());
queryDataBase(minVal);
}
In order to fix this, all I had to do was force the query to wait to run until the spinner updated its value, which was easily done by using SwingUtilities.invokeLater() to force it to the end of the EDT queue, like so:
((JSpinner.DefaultEditor) minRng.getEditor()).getTextField().addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
queryData();
}
});
}
}
});
Thanks to the invokeLater() the query now happens on the new value rather than the previous one, when pressing enter, as the JSpinner has then updated its value to the newly input one.
I'm assuming the reason for this is that the value entered is not officially applied to the JSpinner until you hit enter, which also fires the key listener for the query. The KeyEvent for the custom [query] key listener appears to be the first one in the queue, so it runs its code first, and THEN the KeyEvent for applying the value to the JSpinner from the internal JFormattedTextField, which is why it queries the old value. SwingUtilities.invokeLater() just puts the query itself at the end of the queue, so it allows the other KeyEvent to finish its code before running the query.
Edit:
Another way to achieve this is to request the value directly from the JFormattedTextField rather than the JSpinner, as this should also return the newly entered value since the JFormattedTextField contains the value you typed in, but it hasn't yet been passed to the JSpinner, which appears to be where the issue lies.
private void queryData() {
JFormattedTextField tf = ((JSpinner.DefaultEditor) minRng.getEditor()).getTextField();
int minVal = Integer.parseInt(tf.getText());
queryDataBase(minVal);
}
The only problem with this method is that you then have to catch any NumberFormatExceptions, when parsing the value, where the SwingUtilities.invokeLater() approach allows the spinner model to remove any invalid characters, automatically, and continue with the query.
Anyway, I'm still somewhat inexperienced with Java, so if my understanding of this is incorrect, please let me know in the comments.
I think what you are asking is that when we manually edit the JSpinner shown value, it doesn't actually change it but only show as it.
The reason is that JSpinner use something called editor and has a value. The editor is responsibe for showing the current value and also, changing it (but only using arrow buttons)
If we want to edit it by ourselves then we need to use
spinner.commitEdit();
Have a look into this for further knowledge,
https://docs.oracle.com/javase/7/docs/api/javax/swing/JSpinner.html

Categories