Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
So hard to select a value in a ComboBox populated from an SQLContainer
I'm having a hard time trying to accomplish that.
I have a ComboBox which is populated from an SQLContainer datasource, which consists of simple a collection of rows which come from a simple SELECT * FROM table . I create my combobox with a
myComboBox = new ComboBox("Please select a value", dataSource);
Then I would like to select the value that I have stored in another table. That should be fairly straightforward, but it's a pain because there is no analog method to what .setItemCaptionPropertyId() does.
That is: as well as I have a method to define which column of my datasource I want to use for displaying the human-readable ComboBox items caption, I feel like there should be a method called .setItemIdPropertyId() or similar which could be used to set which column of our datasource would be used as id for the items. Then you should be able to do a
being the parameter eiter for .select() or .setValue(); a value contained in the row that I would had defined previously with that hypotetical .setItemIdPropertyId().
Now I've pulled my hair for hours, even days, trying to figure out to do this with what we actually have. My natural approach is to use .select() or .setValue() (by the way, what's the difference?), creating a new RowId() with the value I'd like to select, but after failing miserably with every attempt, I do a myComboBox.getItemIds() and I discover that they are a collection of ReadOnlyRowId... and each member only has a rowNum property wich belongs to the index of the item, starting from 1, and an inherited id property that is null....
So how in the hell can one select an item based on an id value? This shouldn't be that difficult...
If you have container data source (I am usually not using SQLContainer, but BeanItemContainer), myComboBox.setValue(...) parameter should be Object, e.g. Bean in case of BeanItemContainer. So if you have e.g. Person Bean, you can use .setItemCaptionPropertyId("name"), provided that you have property "name" in Person Bean (i.e. person.getName()). So you can not use myComboBox.setValue("John"), (in case person.getName() = "John"), but myComboBox.setValue(person) instead.
First of all, I have no problem setting the caption. That was just an example to show that, as well as you can set a property to be used as the item's caption, there could be a method to set another property of the container for using it as id or value - that is, what you should set the value of the ComboBox in order to show its belonging item as selected, which is what I was trying to accomplish.
Second, It seems it works in a different way when you're using SQLContainer. At least in that case, ComboBox expects your container to have some Primary Key defined in order for them to be used as the item id. If not, you only have the row number, and the id is null.
I amb using SQLContainer with FreeformQuery, and this way you have to implement by hand so much functionality in a statement delegate for common database actions, and/or passing your primary keys in the constructor of your FreeformQuery (), plus the docs are somewhat obscure about those details, thus having to debug a lot and move through Vaadin source code in order to learn how thinkgs work, so it introduces a lot of hassle for such a simple task.
Finally I ended using TableQuery for this concrete case as my query only involved one table and already implements what is needed to work with ComboBox. But is not the ideal solution as, for instance, there's no way (at least not one I know of) to only specific columns but the whole table.
This approach looks terribly awful to me. Even if you properly map the PKs of the table in your SQLContainer datasource, when you commit the value of the ComboBox you'll get into problems if you only want one single FK value to, let's say, get stored into a record: as it's an array of the values of the PK that belongs to the table/query which populated the control, you'll need to set (and implement) a converter in order to discard the columns you don't want. But - again, as the converter converts in both senses, you won't have a way to get the value of the other PK(s) you discarded because you didn't want its/their value to be stored, so you'll end up doing hackish things in order to accomplish your purposes (I'm referring to selecting an item in the ComboBox). This is horrible and so much pain. Why was this ingeneered that way?? Again, if I'm not doing it the right way, I'd much appreciate some orientation. But when I touch these sensitive themes, I tend to get silence as a response...
Again: as well as we have a .setItemCaptionMode() method, we should have a .setItemValueMode() or some other mechanism in order to configure how the value of the items get assigned and avoid these, in my opinion, absurd situations.
I somewhat agree with you. Personally I am not using ComboBox with container data source very often. Also in Vaadin 8 we have abandoned the container concept as data source.