Combobox does not dispatch a change event when text is same as previous text - apache-flex

If you have a Flex Spark Combobox and enter a value in the text field and press enter a Event.CHANGE event was dispatched. Then if you set the selectedItem to null it erases the value. But if you type in the same value as before and press enter no change event is dispatched. If you enter a different value and press enter a change event is dispatched.
Is there any work around or fix for this?
Steps:
Create a combox, add an event listener and run the application
Type in the value, "test" and press enter
In the event set the combobox.selectedItem to null
Type in the same value, "test" again and press enter
Expected Behavior:
Change event is dispatched again.
Actual Behavior:
Change event is not dispatched. Type in a different value and press enter and the change event is dispatched correctly again.

It appears that ComboBox.previousTextInputText is not being cleared out and that may be the reason it's not dispatching a change event.
It appears that setting ComboBox.openOnInput to false achieves the desired behavior. This is not a real fix but seems to work.

Related

JavaFX uneditable combobox - strange reaction on DELETE keystroke

Preamble
I have uneditable combobox (user can select from list, but can't type). I suppose, when user have focus on it and press DELETE, it's selection must be cleared? It seems that it is (screenshot was made when I selected some value and then pressed DELETE):
selectionModel is null - screenshot
Problem
But UI control still shows old value, it wasn't cleared. Also ValueChanged listener wasn't triggered.
How to cause
Create ComboBox and fill it with some values. Select any value. You already have selection on it, but it's not enough - now DELETE pressing won't even clear selectionModel. The same with selecting by TAB. Select it with double click (expand and collapse) and then press DELETE. Now selectionModel must be cleared, but UI still show your value.
Another thing: if you closed ComboBox, pressing DELETE will trigger ValueChanged listener. Pressing DELETE on expanded ComboBox won't trigger it, but nevertheless value will become null.
Did anybody face with this? Any ideas to make it work naturally i.e. clear selectionModel and update UI?
Well, the problem was not exactly where I thought. "Delete" button did nothing in any case, ComboBox was cleared because it's items list was refreshed every time when it was expanded -> old items were deleted including selected. Problem was the same - UI wasn't updated. So I resolved this by adding ComboBox.getEditor().clear() before refreshing it's items list in onShowing event.

JavaFX ComboBox: Receive mouseclick/keypress events from ListView

I start with the question and then describe the problem more in detail:
Question:
Is there a way to receive events from the listview of a JavaFx ComboBox directly (ComboBox consists of a listview and a textfield as far as I understand)? I would like to find out which element of the list has been clicked by mouse or which element was selected when the user pressed enter on the keyboard (after navigating with Up/Down Arrows in the list). I therefore need to receive the mouse click event or the keypress event on the listview, but all I can get so far are events on the combobox itself which turned out to be only changes in the textfield of the combobox.
Detailed problem description:
I have a JavaFx Application with a combobox where the idea is that the value is directly added to another list when the user clicks on an entry in the combobox list (when the popup of the combobox is open). Additionally, when the user navigates in the combobox list with the arrow keys on the keyboard and he presses enter, the currently selected value should be taken and added to the other list. However so far I have not found out how I can implement this feature with the standard JavaFx combobox.
Tried:
The first solution I tried was to add a change listener on the combobox's valueProperty (this is the value that is displayed in the textfield when the popup is closed). So when the user clicks on a listentry, the popup closes and the clicked entry is put into the value field, changes the value and therefore fires my change listener. This worked well with the mouse, but keyboard navigation did not work correctly because everytime the user navigates down or up on the list, the value field of the combobox is updated with the currently selected listentry and therefore fires my changelistener every time (which in turn adds the value to my other list, while it should only be added on enter keypress).
The next solution was to not add a listener to the valueProperty, but to the showingProperty. Everytime the combobox popup closes, the current value of the value field is taken and added to the other list. This works again well with the mouse, but still has issues with keyboard navigation. While it now correctly handles up/down navigation in the list and enter keypresses, the problem is now when you try to cancel the selection. When you press escape, the value is taken as well and added to the other list like you would have pressed enter. The problem with this approach is that I cannot find out with which keypress the popup has been closed.
So the next idea I had is to add an event filter to the combobox itself with the addEventFilter Method of the ComboBox with code similar to the following (also proposed here StackOverflow):
ComboBox comboBox = new ComboBox();
comboBox.addEventFilter(KeyEvent.KEY_PRESSED, (event) -> {
// do stuff
});
But the event filter never gets called when the combobox popup is open. It is only called when the popup is closed, which leads me to the assumption that the event is consumed by the listview. So the only solution to the problem seems to be to somehow capture the events from the listview itself. And that leads back to the question at the beginning of this post. Sorry for the long explanation.:-)
Came across this question while looking for something else. It touches on something I've worked on before so assuming I understand what you're trying to accomplish and also that this is still relevant here are a couple of ideas.
To keep the other list (list #2) in sync with the combo box for mouse clicks try:
A ChangeListener on the selectedItem property for the combo box's selectionModel. Clicking an item in the popup (drop-down) list view will change the selectedItem value and close the Window that 'owns' the list view, or
An event handler to the combo box for the event type ComboBoxBase.ON_HIDDEN which gets fired when the list view closes (or better said 'becomes hidden').
The ChangeListener may be problematic inasmuch as the selection models for the combo box and the list view are linked at a low level, so that changes to the selectedItem value for the list view which will be triggered when navigating with key strokes will necessarily be handled by the ChangeListener. Since you want to sync the combo box and list #2 only when the ENTER key is pressed, this will probably not work. But that still leaves the event handler idea to try.
As for ENTER key press, you need to get a handle for the list view itself, and then add whatever behavior (listeners/event handlers) as needed. You do this by getting the skin for the combo box, which should be an instance of ComboBoxListViewSkin, and then get the list view by invoking the getPopupContent() method for the skin; it returns the popup list view as a Node so you'll to recast the returned value but no big deal.
Hope this helps.
The idea of the below code is that ListView is created once the combobox is loaded in the JavaFX scene. Therefore, we add a listener on the combobox to check when it appears on the scene, and then through "lookup" method we get its listview and add a listener to it.
In the example, I have set a MouseEvent listener but you can easily adjust it for keys as well.
private EventHandler<MouseEvent> cboxMouseEventHandler;
private void initComboBox() {
ComboBox<String> comboBox = new ComboBox<String>();
comboBox.getItems().add("Item 1");
comboBox.getItems().add("Item 2");
comboBox.getItems().add("Item 3");
comboBox.sceneProperty().addListener((a,oldScene,newScene) -> {
if(newScene == null || cboxMouseEventHandler != null)
return;
ListView<?> listView = (ListView<?>) comboBox.lookup(".list-view");
if(listView != null) {
cboxMouseEventHandler = (e) -> {
Platform.runLater(()-> {
String selectedValue = (String) listView.getSelectionModel().getSelectedItem();
if(selectedValue.equals("Item 1"))
System.out.println("Item 1 clicked");
});
}; // cboxMouseEventHandler
listView.addEventFilter(MouseEvent.MOUSE_PRESSED, cboxMouseEventHandler);
} // if
});
} // initComboBox

How to set the old value which was selected earlier, after a value change event fired

I am facing a problem like I have one Vaadin ComboBox with preselected value.I am changing the value from the ComboBox to another value,then ValueChangeEvent is fired.Inside the valueChange method I have written something to show a Popup Window which has Cancel and Ok button.Upon clicking on OK button of Popup Window I am going with the changed value of the ComboBox but upon clicking on Cancel button I just want to have the old value which was there before value change event fired.
Could anyone please help me out from the above issue?
Thanks in advance.
Maybe you can save whatever SelectedItem the combobox has when the event is fired, and if the user pressed cancel, you reset it to this stored item.
Before the click, how do you know what is selected in the click? Of course, you need to store the current selection somewhere. Lets call it currentSelectedValue (it could be NULL in the begining)
On click, you have a new selection, lets call it newSelectedValue
Now, if you do not want to go with this newSelectedValue, simply do this:
combo.setValue(currentSelectedValue);

Flex focusOut event on TextInput and pop-up does not remove focus?

I have a flex app with several fields and one text field with a focusOut event:
<mx:FormItem label="Last" x="226" y="1">
<s:TextInput id="lastNameClientTextInput" text="#{_currentEditClient.lastName}" change="textFieldChangeCapitalize(event)" focusOut="lastNameClientTextInput_focusOutHandler(event)"/>
</mx:FormItem>
As expected, when I tab or click out of the field after typing a value it executes my "lastNameClientTextInput_focusOutHandler" method which simply pops-up a new window:
protected function lastNameClientTextInput_focusOutHandler(event:FocusEvent):void
{
clientSearchPopUp = new ClientListWindow();
PopUpManager.addPopUp(clientSearchPopUp, this, true);
PopUpManager.centerPopUp(clientSearchPopUp);
}
That window will do a "PopUpManager.removePopUp(this);" when the user clicks the close button.
However, the problem is when the window closes, the focus is back on the lastNameClientTextInput! I am unable to click or tab out of the field!
When I tab out I do initially see the ibeam cursor move from the last name field to the next field in tab order (address) and then my window pops-up. When I close the window it moves BACK to the last name field and highlights the value.
It is as if I need to do something to validate the focusOut event?
You might want to try using valueCommit rather than focusOut. You could also listen for the popup being removed and set focus manually.
HTH;
Amy
Late I know, but Flex may be referring to the FocusManager.lastFocus property to resume focus from the last time the component was active. When triggering the pop up, try calling:
(focusManager as FocusManager).mx_internal::lastFocus = null;

SliderEvent.clickTarget does not change

In my web based flex app I have a HSlider to which 'change' event listener is binded. Inside the event listener function I have the following.
trace('slider click target: '+e.clickTarget);
I am changing the slider value from a timer (say every second). At this time, in the console I see that traget is being printed as null every second.
Now, if I change the value by dragging the thumb, it prints target as thumb. And then onwards it keeps printing the target as thumb every second instead of printing null. The same thing happens if change the slider value by clicking track (it keeps printing track).
Basically, I have the event listener to find out if the value of the slider is changing due to the timer, click on thumb or click on track. Kindly let me know if this issue can be fixed or is there any other approach I can follow. Thanks!!
This is strange, because the documentation says that the change event is dispatched when the slider changes value due to mouse or keyboard interaction - the event is not triggered when you change it programmatically, and the listener shouldn't even be called.
Are you calling the event listener manually? Post some more code - where you update the slider value and the full event listener.

Resources