What kind of property to use for "NativeSelect"

Hi,

I am using Vaadin 6.8.x.

How can I find out which “Property” to use with “setPropertyDataSource(theProperty)” for a certain component?

Example:

Component <=> DataSource

TextField <=> ObjectProperty
NativeSelect <=> [?Some kind of collection?]

===

Indeed I don’t know which property to use for a NativeSelect. Is there an overview of “Component2DataSource”?

Thanks!

Mario, not sure that I entirely understand your question, so I will give quick answer in hope that someone will be able to provide better answers.

Property foo = sqlConstiner.getItem(sqlContainer.getIdByIndex(1)).getItemProperty(“foo”);
Textfield field = new TextField(foo);

Basically you need to be able to define it as a property

Cheers

I would strongly recommend starting with reading the
data model chapter
in the book or other similar material and then looking at some examples or tutorials.

A selection component in Vaadin has both a property data source (the currently selected value(s)) and a container data source (all values displayed), which are usually completely separate. The property data source should have the value type of its item IDs, or a Set of the item ID type if in multi-select mode.

A Field can have any property data source with a suitable data type. A TextField does not require an ObjectProperty but can use any property which has a value of a suitable data type - usually String. Likewise, a NativeSelect can use any Property that has a suitable value type.

As Curtis’ example shows, in most cases, you don’t want to create a property instance to use as the property data source for a field but instead bind the field to a Property instance that comes from an Item that may come from a Container. Very often, you don’t even know the actual type of the Property, nor care about it.

Hi guys,

thanks for your explanations.

I have got a NativeSelect.

  • This component has one container.
  • The container has X items (of type PropertysetItem).
  • Each item has one property (of type ObjectProperty), whereas the item id is the String

propertysetItemOne.addItemProperty("one", objectPropertyOne);
propertysetItemTwo.addItemProperty("two", objectPropertyTwo);
propertysetItemThree.addItemProperty("three", objectPropertyThree);

indexedContainer.addItem(propertysetItemOne);
indexedContainer.addItem(propertysetItemTwo);
indexedContainer.addItem(propertysetItemThree);

nativeSelectField.setContainerDataSource(indexedContainer);

:slight_smile: - Showing all items in component does work
:slight_smile: - When selecting an item the model gets updated property
:frowning: - What NOT works: selecting an item progammatically. I tried it with nativeSelectField.setValue() and nativeSelectField.select()

==

  • Did I get it right that it is not necessary to create ObjectProperties? It looks like a big overhead to me…?
  • There is no table of “suitable data types” for all the Vaadin components?

The problem with the Book of Vaadin is the documentation on binding Properties to AbstractSelect implementations (NativeSelect, ComboBox, etc.) is poor. I’ve reread Chapter 9 multiple times and there is no information of which implementation of the Item interface (PropertsetItem, BeanItem, etc.) is recommended for an AbstractSelect implementation, nor which implementation of the Property interface should be used in addItemProperty(), nor even if the call to addItemProperty() is itself the recommended one.

In short, the Book of Vaadin is missing an example of binding an AbstractSelect to a FieldGroup in a way that works and is easy to understand.

Indeed, the code you should use is much simpler. Note also that a ComboBox has a default container if you don’t set one. If you use the default one, it is as simple as
this example
(much of the API for ComboBox and NativeSelect is the same).

When you use a Container - e.g. IndexedContainer - it is the container that creates Items and Properties of the appropriate type. You should never add a pre-constructed Item or Property instance to any of the standard containers.

In most applications, you don’t even need to know what Property and Item implementations exist apart from the often useful BeanItem (which you might want to create explicitly when not using a BeanItemContainer/BeanContainer).

If you check the javadoc or other documentation for IndexedContainer.addItem(Object itemId), it states that the parameter should be the item ID. If you give it a Property instance, what happens is that the property you gave is only used as an item ID for the real property of the container (the actual type of which you don’t even need to know). Your code would require using the property instances as the IDs for fetching data from the container etc. which is definitely not what you want.

Thanks for your answer. Very helpful so far. But I have more questions…

Lets assume I have

  • a view object (with a NativeSelect)
  • a presenter (where I need to bind the selected value of the NativeSelect to a model. The corresponding field in the model is a String)

So I fill my Container (IndexedContainer) with the possible values

container.addItem("1");
container.addItem("2");
container.addItem("3");

Add the container to the nativeSelect

getNativeSelectFromView().setContainerDataSource(container);

I would be able to preselect a value

getNativeSelectFromView().setValue("3");

which wouldn’t be any binding though!

I would assume to bind with

getNativeSelectFromView().setPropertyDataSource(aProperty);

But as you said I (as a developer) shouldn’t care about Items and Properties.

Question: How to bind the model to the NativeSelect? Means: How to make sure that the model gets updated if a user changes the selected value in the GUI?
Hint: Using Vaadin 6.8.x

Thanks again!

Unfortunately, that example does not demonstrate how to bind a ComboBox or NativeSelect to a FieldGroup, so that later on when commit() is called, the validate() method of the appropriate Validator is called.

Mario, this is what I did to validate my ComboBox, after much trial and error. Note the use of the @PropertyId annotation. Without the item.addItemProperty() calls, the validators will not get called when commit() is called on the FieldGroup.



class MyView() {


  @PropertyId("programExchange")
  private ComboBox myComboBox;

  class MyComboBoxValidator implements Validator {

    private static final long serialVersionUID = 1L;

   @Override
    public void validate(Object value) throws InvalidValueException {
      int numItems = myComboBox.size();
      // If there are loaded items, make sure one of them is selected
      // If there are none, don't worry about it.
      if (numItems > 1) {
        Object selection =  myComboBox.getValue();
        String messageTypeStr = (String) msgTypeSel.getValue();
        if (messageTypeStr != null && selection == null) {
          MessageType messageType = MessageType.valueOf(messageTypeStr);
          if (MessageType.STATION_INFORMATION.equals(messageType)
              || MessageType.PROGRAM_MARKETING.equals(messageType)) {
            return;
          }
          throw new InvalidValueException(
              "Please select a valid Item.");
        }
      }
    }

  }
PropertysetItem item = new PropertysetItem();

myComboBox = new ComboBox();
myComboBox.addValidator(new MyComboBoxValidator();

Button btn = new Button("Send");
    btn.addStyleName("cd-primary icon-white icon-download");
    btn.setIcon(new CssGlyphIconResource());
    btn.setSizeUndefined();
    btn.addClickListener(new Button.ClickListener() {

      private static final long serialVersionUID = 1L;

      /**
       * Send the message upon button click, after validation
       */
      @Override
      public void buttonClick(ClickEvent event) {
        try {
          // Run the validation
          binder.commit();
        }
        catch (CommitException e) {
          errorLabel
              .setValue("Unable to submit. Please correct the above errors.")
          return;
        }
  }

item.addItemProperty("programExchange", new ObjectProperty<String>("",
        String.class));

binder = new FieldGroup(item);
    binder.bindMemberFields(this);

@Mario, I can only tell about the “normal” combox, but assuming there’s no difference between them, the binding of a combobox field to a property is exactly the same as binding it to a textfield. You can wrap your model/bean in a BeanItem and then set the property datasource accordingly. Say you have a bean with a String property “name” and for some reason want to bind it to a combobox on the UI side. Your bean looks like this:

public class SimpleBean {
[indent]

[/indent]private String name;

... getter and setter...
}

Then you create the combobox with the possible values:

ComboBox nameCombo = new ComboBox();
nameCombo.addItem("A");
nameCombo.addItem("B");
nameCombo.addItem("C");
...

Then you wrap your bean in a BeanItem and bind it to the UI:

SimpleBean bean = new SimpleBean; // or load it from the database or whereever
BeanItem<SimpleBean> beanItem = new BeanItem<SimpleBean>(beanItem);
nameCombo.setPropertyDataSource(beanItem.getItemProperty("name");

It’ also possible to preselect a value using

nameCombo.select("A")

but you have make sure you do this after you set the property datasource (otherwise the preselected value will be overwritten by the actual value from the bean):