Set combobox items dynamically based on search query - java

I have a combobox that I would like to act as a search field. When I enter some value I want to call a backend service that would based on the entered value return a list of possible values. I would like to set these values as the combobox items dynamically. So far I have this code:
ComboBox<String> comboBox = new ComboBox<>("Name");
comboBox.setAllowCustomValue(true);
comboBox.setAutofocus(true);
comboBox.addCustomValueSetListener(e -> comboBox.setItems(backendService.getData(e.getValue())));
This works, but it is not ideal, as I (the user) has to type the value, hit enter and focus the combobox again. At this point the matched values from backend are set as items in the combobox. Is there a way to fetch items from the backend dynamically as the user writes in the input with some time delay (e.g. ValueChangeMode.LAZY for TextField) and set them as combobox items while writing user input?

After reading through this link I found a solution using lazy data loading. I had to adjust my backend service to accept a PageRequest object, so the following line of code did exactly what I wanted:
comboBox.setItems(query ->
backendService.getData(PageRequest.of(query.getPage(), query.getPageSize())));

Related

Label visibility on filtered list search in JavaFX

I'm using a TextField with a listener to filter a TableView. I've got if statements that set the predicate if newText matches part of the ID or Name.
The search functionality works like I want.
However, my project guidelines require me to also create some form of output upon a search not matching any objects in the TableView.
I created a Label and set the visibility to false to start. I placed the code to set the Label to visible after each of the if statements in the predicate logic so that it only shows if none of the statements are valid. I then placed a line setting it back to false at the beginning of the predicate logic so on each listener change it gets reset.
I am having an issue where if my search returns the last item in the list it is fine and the label doesn't appear, but if the search doesn't return the last item in the list then the label becomes visible even though the search displays items from the sorted list.
The following is my code and I've attached screenshots of the "bug".
FilteredList<Part> filteredParts = new FilteredList<>(Inventory.getAllParts(), p -> true);
partFilter.textProperty().addListener((ob, ol, newValue) -> {
filteredParts.setPredicate(text -> {
//each time listener is updated sets label visibility to false
partSearchMismatch.setVisible(false);
//If searchbar is empty or null it displays all parts
if (newValue == null || newValue.isEmpty()){
return true;
}
//if text matches partID
String lowerCaseFilter = newValue.toLowerCase();
if(String.valueOf(text.getId()).contains(lowerCaseFilter)){
return true;
}
//if text matches part name
if(text.getName().toLowerCase().contains(lowerCaseFilter)){
return true;
}
partSearchMismatch.setVisible(true); //if no matches, displays label
return false; //no match
});
});
//Wraps filtered list in sorted list
SortedList<Part> sortedParts = new SortedList<>(filteredParts);
//Binds sorted list comparator to the parts table comparator
sortedParts.comparatorProperty().bind(partsTable.comparatorProperty());
partsTable.setItems(sortedParts);
The following is the base sample data in table
Image of search that matches first object in list but label showing anyways
Image of search that matches second object in list but label showing anyways
Image of label working as long as last object in table is included in search
my project guidelines require me to also create some form of output upon a search not matching any objects in the TableView.
That will happen by default, when the filtered table does not have any matches for the filter, the table will display a placeholder. The placeholder node is configurable, so you can set it display anything you want.
You don't need an additional label and logic to show that nothing would be displayed in the table unless you have an additional requirement for that.
Okay, so it's the placeholder text that I see in the table that says "no content in table"? I should just be able to set that to something that mentions the search didn't return anything. Thank you. I am still curious what I am doing wrong with the label though
The predicate is a boolean function, it should be executed without side effects. You set the predicate on the filtered list, but you don't know or have any control over when the filtered list will choose to execute that code. The predicate may be executed many times to filter each individual item in the list. If you put side effects in the predicate like setting label visibility, you don't really know what will happen unless the operations are idempotent (they aren't).
Instead, have the predicate evaluate the lambda input object to see if it should be filtered or not, only returning true or false and doing nothing else.
That you name the input parameter to the predicate as text indicates that you don't really understand it. The input parameter is a Part, an element of the observed list, it is not text, so it would make sense to name it part and not text. Also (and this is just style, not functional), to help make the code easier to read, use a descriptive name for the new text in the listener (e.g. filterText or newSearchText rather than newValue).
For a concrete example of searching a table using a filtered list and a text field, see, the Eden Coding tutorial:
Search bar with predicates.
As noted by Slaw in comments:
If the placeholder is not enough, I would try to use bindings.
Something like:
label.visibleProperty().bind(
Bindings.isEmpty(filteredParts)
.and(
partFilter.textProperty().isNotEmpty()
)
)
);
Or you can move the logic for the label notification setting out of the predicate but keep it in the change listener for the search text field (this essentially does a similar job to the binding).

Play framework forms repeated values - dynamically add controls for new values

I'd like to create a Play form that allows users to enter multiple values for a list in my model. Initially the form should show a single text box, but clicking a "+" button should create a new text box to allow them to enter another value.
The closest I've found is the Play framework documentation on repeated values: https://www.playframework.com/documentation/2.1.0/JavaFormHelpers but this only works for forms pre-populated with multiple email addresses (code below for completeness). How could I add a button to dynamically create a text box to allow the user to add a new email?
#inputText(myForm("name"))
#repeat(myForm("emails"), min = 1) { emailField =>
#inputText(emailField)
}
In my actual model, the list values are actually objects with multiple fields, but I assume if I can add an email field, I'll be able to construct what I need.
Many thanks,
Jim

String Tokenizer.nextElement for JComboBox

I'm using
int TxtAge = Integer.parseInt(tfAge.getText().trim());
to get value from my textfield and search it in database.
Then, I'm using Integer age = Integer.parseInt(stringTokenizer.nextElement().toString()); to go to next attributes in my database.
I have no problem using those codes for textfield but when I'm using the JComboBox the result won't display. How to use the StringTokenizer.nextElement() for JComboBox? Is is the same with TextField?
String sex=(String) stringTokenizer.nextElement();
I tried this code but still failed :(
You seem to have left out the relevant portions of your code, i.e. how you are handling setting/getting items in the JComboBox. Whether you read these values from a database, a file or have them hardcoded is irrelevant to the question.
Since you do ask whether it is the same as with a JTextField, I can at least answer this; it is not the same. The question indicates that you're quite new to Swing. You would probably benefit from working through a basic Swing tutorial, just to get a grip on how to work with these basic GUI elements. For JComboBox, check out Oracles own How to Use Combo Boxes.
Anyways, when working with JComboBox, you will need to first populate it with the values that users can choose from and set the currently selected value. Retrieving the currently selected value is just a simple method call.
Further, you have the possibility of making a combobox editable. This means that the user can edit the text in the combo box to something that was not pre-populated. By default, this option is turned off.
I'll provide some examples.
Initialize:
JComboBox sexComboBox = new JComboBox();
sexComboBox.addItem("Not selected");
sexComboBox.addItem("Male");
sexComboBox.addItem("Female");
sexComboBox.addItem("Do not want to disclose");
By default, the first item you added is selected. To select another one, you need to add one of the following lines:
sexComboBox.setSelectedIndex(1); // zero-based index, "Male" is selected item
sexComboBox.setSelectedItem("Female"); // sets the selected item to "Female"
To enable user to edit the contents to something that was not pre-defined, just add the line:
sexComboBox.setEditable(true);
To retrieve the currently selected value:
String selectedItem = (String) sexComboBox.getSelectedItem();

Retrieving current user entered value from GWT SuggestBox

I'm new to GWT. I have a simple SuggestBox which is populated using a MultiWordSuggestOracle. Users input their data to this SuggestBox, and if they find any match with the existing Suggestions its well and good. I'm able to retrieve this value in the SelectionHandler code as below.
display.getSuggestBox().addSelectionHandler(new SelectionHandler<Suggestion>() {
public void onSelection(SelectionEvent<Suggestion> event) {
String selectedProperty = ((SuggestBox)event.getSource()).getValue();
// do something with the property value
}
});
But users are allowed to enter values which are not already in the Suggestion oracle, in which case I should read this value and do something with this,may be saving to db as a new data.(The thing which I'm looking for is something like a browsers navigation widget where we show suggestions, users can pick up any suggestion or he can type in his new entry and carry on.) What I needed is a way to retrieve this new text user has entered? Data will be read on a button click. What I tried out is this.
display.getSaveBtn().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
String selectedProperty = display.getSuggestBox().getValue();
//String selectedProperty2 = display.getSuggestBox().getText();
// Blank in both cases :(
// tried display.getSuggestBox().getTextBox().getValue(),but blank again
}
});
I tried to employ onChange() event handlers (as shown below)
display.getSuggestBox().addValueChangeHandler(new ValueChangeHandler<String>() {
public void onValueChange(ValueChangeEvent<String> event) {
String selectedProperty = ((SuggestBox)event.getSource()).getValue();
Window.alert("on change -- "+selectedProperty);
}
});
This is working fine except one scenario. Suppose there are two suggestions in the oracle,say 'createTicketWsdl' and 'createTicketTimeout'. When the user types in 'cr', he is opted with these two options, and if he selects 'createTicketWsdl' by pressing keyboard ENTER, then my alert is printing 'createTicketWsdl' which is correct. But if he selects 'createTicketWsdl' using mouse, then my alert is printing 'cr' (I tried to post the screenshot to give a better understanding, but being a new user I'm not allowed).(which I wanted to get as 'createTicketWsdl'since thats what he has selected). Soon after printing my alert, the value in the SuggestBox changes to 'createTicketWsdl'.
Is there a way to retrieve the value of the suggest box? I saw a similiar thread GWT SuggestBox + ListBox Widget, where some source code for a custom widget is available. But I didn't take the pain of trying out that, since what I want is simply get the current value from the SuggestBox and I hope there should be some easy way.
Thanks for all your help!
Your question is not very clear. You need to clarify your language a lil' bit. For example - is the following a question or an assertion? I mean, it sounds like an assertion but it has a question mark.
What I needed is a way to retrieve this new text user has entered?
Also, I do not understand what you mean by "he is opted by". Did you mean to say, "he is presented with the options ..." ?
Therefore, I am guessing your situation.
You have a listbox of existing items.
You have a textbox which allows freeform text entry
Any items whose prefix values matches the current textbox entry, the listbox items would be filtered to be limited to the matching items.
Even if the current textbox entry presents matching prefixes to filtering the listbox, the user can still perform freeform text entry. So, there are two possible cases here
4.1 the user clicks on the list box to select one of the filtered items
4.2 the user press enter key, which triggers selection of the current value of the textbox.
However, you find your widget participating in a race condition, so that when you click on the widget, the ValueChangeHandler gets triggered rather than the SelectionHandler. I do not know the structure of your widget so that is my best guess.
The problem is that you are allowing two separate modes of obtaining an outcome and you probably did not have well-defined state machine to handle choosing the appropriate mode. One mode is by the textbox and the other is by selection on the listbox - and you do not have a well-defined way of which would mode would be effective at any moment.
If my guess is accurate, this is what you need to do:
You must restrict your outcome to coming from only the textbox.
Your listbox selection must not trigger any outcome. Any change in listbox selection must propagate back to the textbox - to allow the user the chance of making further freeform entry based on that value.
only the keyboard enter on the textbox will trigger the final outcome.

automatically display the selected item in jcombobox

I'm done with retrieving data from MySQL to JComboBox.
It worked successfully.
Initial
I choose category "OTHERS" over "INGREDIENTS" then saved it.
But when I use the search button, the category display INGREDIENTS instead of OTHERS.
my problem is that I want to display OTHERS (or whatever category I choose)
If this code will retrieve my data in the field:
inventCodeField.setText(rs.getString("ItemCode"));
How can I retrieve the data I selected from the JComboBox without removing the other choices?
After querying the specific record, extract the field value for category then use it as a parameter for setSelectedItem() of JComboBox class.
// assume that category is a String that holds the category value after querying
cbo_category.setSelectedItem(category);

Categories