Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
Vaadin 8 and private BeanContainer
Im my app I use:
private BeanContainer<Long,TbPedido> pedidoContainer = new BeanContainer<Long,TbPedido>(TbPedido.class);
so, how I replace to new in vaadin8?
tks
There's no replacement for Containers. Grids and select components are parameterized with the bean type and you can add the beans directly. For example:
List<Person> persons = Backend.getPersons();
Grid<Person> grid = new Grid<>(Person.class);
grid.setItems(persons);
Alejandro in my sample I use one ID in this case a Long value, so when I need to get one bean in my container I only need to use container.getItem(id), So I have this same behavior in grid with vaadin8?
Fabio Ebner: Alejandro in my sample I use one ID in this case a Long value, so when I need to get one bean in my container I only need to use container.getItem(id), So I have this same behavior in grid with vaadin8?
This feature is no longer present in V8 Grid, since it doesn't store any of the beans and the data provider might be lazy.
But since you're using an in-memory ListDataProvider (because you use `grid.setItems(Collection)`, you can get the DataProvider from Grid, and cast it to a ListDataProvider, then iterate through the items to find the item with the corresponding ID.
Puja Kuamri: how to replace Item in vaadin 8
There's no replacement for it. The Item
interface has been removed completly in Vaadin 8. Now you can use your own types (domain) without having to worry about Property
, Item
, and Container
.
This is what I confused. I want to build a Grid with some data in a Product bean and a extral String column. I found out I can use IndexedContainer or other container to customize a grid in old version. But V8 doesn't support it any more. It makes customize grid so difficult. More works.
Hey Yong Liu !
As i understand, you want to add some collumns that are dependding from the Bean model, and a column that is depending on something else ?
there are numeriuous ways to do it, to find the best solution for you, i need more data :)
you could use a suplier, which fetchs the right data for the custom column for example
Or you could use a Wrapper Object, which has the Bean as parameter, and also data for the custom Column.
If you would post the old way for that one column, maybe it is easyer to help you then :)
You can do that in addColumn(..) method by giving lambda expression for value provider, e.g. the one below sets all cells in the column "String" to have value "My string".
addColumn(myString -> "My string").setCaption("String");
And you can have a method that depends from some inputs to produce the value as well, something like.
addColumn(myString -> getString(..)).setCaption("String");
Thank you,guys. It's really help. Finially I wrapped my bean with some columns. @Vilius. Do you know any sample or demo about how to use supplier?
Do you guys know how to binding CheckBox with a boolean property?
CheckBox residential = new CheckBox("Residential");
recipientAddressBinder.bind(residential, Address::getResidential,Address::setResidential);
My residential in Address is a boolean. The binder match the string with checkbox's caption, not the value. Do you have any ideas? Thank you.
I guess I can use withConverter
to solve it. But I don't know how.
private Binder<Address> recipientAddressBinder;
recipientAddressBinder = new Binder<>(Address.class);
I also binded other components with Address. They are working well.
TextField country = new TextField("Country");
TextField contactName = new TextField("Contact Name");
TextField companyName = new TextField("Company Name");
companyName.setWidth("100%");
TextField add1 = new TextField("Address Line 1");
TextField add2 = new TextField("Address Line 2");
TextField add3 = new TextField("Address Line 3");
TextField postalCode = new TextField("Postal Code");
TextField stateNprovinceCode = new TextField("State/Province");
TextField city = new TextField("City");
TextField telephone = new TextField("Telephone");
CheckBox residential = new CheckBox("Residential");
residential.addStyleName("");
recipientContactBinder = new Binder<>(Contact.class);
recipientAddressBinder = new Binder<>(Address.class);
recipientContactBinder.bind(contactName, Contact::getPersonName, Contact::setPersonName);
recipientContactBinder.bind(companyName, Contact::getCompanyName, Contact::setCompanyName);
recipientContactBinder.bind(telephone, Contact::getPhoneNumber, Contact::setPhoneNumber);
recipientAddressBinder.bind(country, Address::getCountryCode, Address::setCountryCode);
//recipientAddressBinder.bind(add1,Address::getStreetLine1,Address::setStreetLine1);
//recipientAddressBinder.bind(add2,Address::getStreetLine2,Address::setStreetLine2);
//recipientAddressBinder.bind(add3,Address::getStreetLine3,Address::setStreetLine3);
recipientAddressBinder.bind(postalCode, Address::getPostalCode, Address::setPostalCode);
recipientAddressBinder.bind(stateNprovinceCode, Address::getStateOrProvinceCode,
Address::setStateOrProvinceCode);
recipientAddressBinder.bind(city, Address::getCity, Address::setCity);
//recipientAddressBinder.bind(residential, Address::getResidential,Address::setResidential);
GridLayout recipientLayout = new GridLayout(3,6);
recipientLayout.setSizeFull();
recipientLayout.setSpacing(false);
recipientLayout.setMargin(false);
recipientLayout.addComponent(country,0,0);
recipientLayout.addComponent(residential,2,0);
recipientLayout.addComponent(contactName,0,1);
recipientLayout.addComponent(companyName,1,1,2,1);
recipientLayout.addComponent(add1,1,2,2,2);
recipientLayout.addComponent(add2,1,3,2,3);
recipientLayout.addComponent(add3,1,4,2,4);
recipientLayout.addComponent(postalCode,0,4);
recipientLayout.addComponent(stateNprovinceCode,0,3);
recipientLayout.addComponent(city,0,2);
recipientLayout.addComponent(telephone,1,0);
Panel recipientPanel = new Panel("<h3><strong>Recipient Information</strong></h3>");
recipientPanel.setSizeFull();
recipientPanel.setHeight("50%");
recipientPanel.setContent(recipientLayout);
@Yong Liu about Supplier.
As i understood, you wanted to add some Columns, which represent something, that is not in the bean. (maybe i also totaly misunderstood you, sorry if this is the case, it is late :)
As the Supplier gives you a at that moment when you are "asking" him to, withou you giving anything as request, i was thinking of it as possible Solution.
Example for Grid.
simple bean class
public class Pojo {
private Long id;
private String name;
public Pojo(final Long id, final String name) {
this.id = id;
this.name = name;
}
//getter setter
}
a minimalistic grid that shell show the name of pojo, and also completely undependent column, something completely random :)
Random rn = new Random();
Supplier<Integer> supplier = () -> rn.nextInt(1000);
Grid<Pojo> grid = new Grid<>();
grid.addColumn(Pojo::getName)
.setCaption("Name");
grid.addColumn(p -> supplier.get())
.setCaption("TimeStamp");
Collection<Pojo> pojos = new ArrayList<>();
LongStream.range(0, 100)
.forEach(i -> pojos.add(new Pojo(i, "Pojo Nr.:" + String.valueOf(i))));
grid.setItems(pojos);
as a result, i got this grid
I dont know if it is fitting for you, just wanted to show a way of adding columns, that have nothing to do with the actual bean. If you want something like this but to give Bean as a Parameter, try "Function<T, R>"
Represents a function that accepts one argument and produces a result.
about the recipientAddressBinder.
just a quick hope, you wrote
CheckBox residential = new CheckBox("Residential");
recipientAddressBinder.bind(residential, Address::getResidential,Address::setResidential);
residential is boolean, the default getter should be isResidential not getResidential
maybe that was the issue ?
Thank you @Vilius. That's what I want. Thank you very much.
I'm not sure the binder can use as recipientAddressBinder.bind(residential,Address::isResidential)
. I looked up javadoc. But can't find any infomation about it. And it can't use as recipientAddressBinder.bind(residential,Address::isResidential,Address::setResidential)
.The binder will validate getter and setter.
<Boolean> Binding<Address, Boolean> com.vaadin.data.Binder.bind(HasValue<Boolean> field, ValueProvider<Address, Boolean> getter, Setter<Address, Boolean> setter)
You are very welcome Yong Liu.
Can you check what the boolean getter and setter Methods in your model class are?
if you use lomebock, it is dependent if its Boolean or boolean.
if they are "human written" there can be mutants like "setIsResidential" and stuff like that :)
I tried your lines at an simple example at home yesterday, and it worked with my example model class, which had "is" at begin :)
Thank you for reminding me. I tracked down every step in my project. The problem is rs.getString("RESIDENTL")=="Y"?true:false
not working. I changed to rs.getString("RESIDENTL").equals("Y")?true:false
. The CheckBox is working well now.
btw, you can simply change the code to
return ("Y").equals.(rs.getString("RESIDENTL"));
without ?true:false; Its shorter, and wont throw an Null Pointer if rs.getString("RESIDENTL") == null :)
Thanks.@Vilius. I have a question about execute server-side funcation in a ButtonClickEvent. My code kind like below.
public class FedexShipView extends CssLayout implements View{
private static ContentBean cb = new ContentBean();
private Binder<Address> addressBinder;
public FedexShipView(){
TextField add = new TextField();
addressBinder.bind(add,Address::getAddress,Address::setAddress);
Button clear = new Button("clear",new ClickListener(){
@Override
public void buttonClick(ClickEvent event) {
clearForm();
**How to execute server-side function at here?**
}
}
});
CssLayout cly = new CssLayout();
cly.addComponents(clear,add);
}
public void setContent(ContentBean cb){
this.cb = cb;
addressBinder.readBean(cb.getAddress());
}
public void clearForm(){
addressBinder.removerBean();
}
}
I understand addressBinder is a server-side object and ButtonClickEvent comes from client-side. But how to make it work?
thank's to Vaadin, you do not have to think about "client side / server side"
i assume you use java8 or later ?
if you need the ClickEvent as a parameter, you can simply write clickEvent as lambda Expression, it is nicer to read then anonymous class.
...
Button clear = new Button("clear", event -> handleClearClick(event));
...
private void handleClearClick(final Button.ClickEvent event) {
clearForm();
getDataFromBackend();
doWhatEverYouWant();
}
if you do not need the event as parameter, you can simply write like
...
Button clear = new Button("clear", e -> handleClearClick());
...
private void handleClearClick() {
clearForm();
...
}
hope this was helpfull.
Yes. I'm using Java8. Base on your code. I did some test. Below is my test code. setAdd()
and isChanged()
are working well. clearForm()
is still not working.
public class TestBinderView extends VerticalLayout implements View {
public static final String VIEW_NAME="Test View";
private Binder<Address> addressBinder;
private Address address;
public TestBinderView() {
Address recipientAddress = new Address();
recipientAddress.setStreetLines(new String[] {"Some Where"});
recipientAddress.setCity("WEST BLOOMFIELD");
recipientAddress.setStateOrProvinceCode("MI");
recipientAddress.setPostalCode("48322");
recipientAddress.setCountryCode("US");
recipientAddress.setResidential(false);
addressBinder = new Binder<>(Address.class);
TextField city = new TextField("City");
addressBinder.bind(city, Address::getCity,Address::setCity);
Button add = new Button("Add",event-> {
this.setAdd(recipientAddress);
});
Button clear = new Button("Clear",event->{
this.clearForm();
});
Button valChange = new Button("Change",event->{
this.isChanged();
});
HorizontalLayout hl = new HorizontalLayout();
hl.addComponents(city,add,clear,valChange);
this.addComponent(hl);
}
private void setAdd(Address add) {
this.address = add;
addressBinder.readBean(address);
}
private void clearForm() {
addressBinder.removeBean();
//addressBinder.setBean(null);
}
private void isChanged() {
if(addressBinder.hasChanges()) {
UI.getCurrent().showNotification("text changed.");
}
}
}
So I debuged the code. Below is the setBean in Binder.class. It skiped over on if (this.bean != null)
public void setBean(BEAN bean) {
checkBindingsCompleted("setBean");
if (bean == null) {
if (this.bean != null) {
doRemoveBean(true);
clearFields();
}
} else {
doRemoveBean(false);
this.bean = bean;
getBindings().forEach(b -> b.initFieldValue(bean));
// if there has been field value change listeners that trigger
// validation, need to make sure the validation errors are cleared
getValidationStatusHandler().statusChange(
BinderValidationStatus.createUnresolvedStatus(this));
fireStatusChangeEvent(false);
}
}
Than I thought there was no Bean in binder when I do removerBean(). I add below code to clearForm()
than I got a java.lang.NullPointerException
.
UI.getCurrent().showNotification("city:"+addressBinder.getBean().getCity());
Do you have any idea about this ?
About the nullpointer, yes.
lets check the removeBean() from binder.
/**
* Removes the currently set bean and clears bound fields. If there is no
* bound bean, does nothing.
* <p>
* This is a shorthand for {@link #setBean(Object)} with {@code null} bean.
*/
public void removeBean() {
setBean(null);
}
so bean == null after that. so if you do
addressBinder.removeBean();
addressBinder.getBean().getCity()
You will get nullpointer, because it is basicaly
null.getCity();
btwm removeBean simply sets the bean to null.
Based on the name, i assume, that you want to reset all yout binded fields ?
There are many ways to do so.
You can reset your Bean Values and make binder.readBean afterwards. (you have to implement the reseting method first)
You can reset you inputFields directly, and call "writeBean(bean)"
/**
- Writes changes from the bound fields to the given bean if all validators
- (binding and bean level) pass.
-
- If any field binding validator fails, no values are written and a
- {@code ValidationException} is thrown.
-
- If all field level validators pass, the given bean is updated and bean
- level validators are run on the updated bean. If any bean level validator
- fails, the bean updates are reverted and a {@code ValidationException} is
- thrown.
You can create fresh Bean object and then set it in the binder (you lose the ID, and i dont know what is happening in your code, when creating the Object)
ofcourse you can simply make binder.readBean(null) or binder.setBean(null) BUTT !!!!!!
if at any moment you will do something like binder.getBean().doSomething(); you will get a NullPointer !
Insted of writing something like
if (addressBinder.getBean() != null) {
UI.getCurrent().showNotification("city:"+addressBinder.getBean().getCity());
}
I would try to make sure, that the bean is never set to null :)
But i dont know your programm as well as you do, it is your desission :)
Yes. Only thing I want to do is empty all binded fields. I don't think setBean(null)
will reset field in this case because removerBean
called setBean(null)
in Binder.class.
Those below two ways will reset fields and I tested them.
private void clearForm() {
Address newAdd = new Address();
addressBinder.setBean(newAdd);
}
private void clearForm() {
addressBinder.readBean(new Address());
}
I didn't get it. Is this means Binder realse the bean after inject data to field and add a kind of valueChangeListener to the field to monitor data changing? I don't know if binder desgind by this way or it's a bug.
I would say, best simply go to the com.vaadin.data.Binder methods you are using and check the JavaDoc.
removeBean() simply sets bean to null. it does nothing with the Fields.
lets check the setBean
public void setBean(BEAN bean) {
...
if (bean == null) {
...
} else {
...
this.bean = bean;
** getBindings().forEach(b -> b.initFieldValue(bean));**
...
}
}
as you see, afte rsetting the bean, the "initFieldValue" will be triggered. If the values are empty strings, it will be set to empty strings :)
same in readBean
public void readBean(BEAN bean) {
...
if (bean == null) {
...
} else {
...
** getBindings().forEach(binding -> binding.initFieldValue(bean));**
...
}
}
Yes. I understand that. Below is the JavaDoc about removeBean. Removes the currently set bean and
clears bound fields
removeBean
public void removeBean()
Removes the currently set bean and clears bound fields. If there is no bound bean, does nothing.
This is a shorthand for setBean(Object) with null bean.
Let me explain this clearly. In below code.
-
Click
Add
button. The TextField value change toWEST BLOOMFIELD
. -
Click
Clear
button. Nothing happened.
I think Clear button should be empty the TextField. But it doesn't. Is this right?
public class TestBinderView extends VerticalLayout implements View {
public static final String VIEW_NAME="Test View";
private Binder<Address> addressBinder;
private Address address;
public TestBinderView() {
Address recipientAddress = new Address();
recipientAddress.setStreetLines(new String[] {"Some Where"});
recipientAddress.setCity("WEST BLOOMFIELD");
recipientAddress.setStateOrProvinceCode("MI");
recipientAddress.setPostalCode("48322");
recipientAddress.setCountryCode("US");
recipientAddress.setResidential(false);
addressBinder = new Binder<>(Address.class);
TextField city = new TextField("City");
addressBinder.bind(city, Address::getCity,Address::setCity);
Button add = new Button("Add",event-> {
this.setAdd(recipientAddress);
});
Button clear = new Button("Clear",event->{
this.clearForm();
});
Button valChange = new Button("Change",event->{
this.isChanged();
});
HorizontalLayout hl = new HorizontalLayout();
hl.addComponents(city,add,clear,valChange);
this.addComponent(hl);
}
private void setAdd(Address add) {
this.address = add;
addressBinder.readBean(address);
}
private void clearForm() {
addressBinder.removeBean();
addressBinder.setBean(null);
//addressBinder.readBean(new Address());
}
private void isChanged() {
if(addressBinder.hasChanges()) {
UI.getCurrent().showNotification("text changed.");
}
}
}
This class is a View in a Navigator.
No it wont and it is to see in
public void setBean(BEAN bean) of Binder.
first you remove Bean, so the Bean of Binder is null.
then you setBean(null)
lets make a breakpoint in the Binder of vaadin.
As you surely see, it checks first if the bean from parameter is null. IT is in our case, so it wont ever come to that code in "else"
Now it checks, if the this.bean is != null, but you just made it null with removeBean :)
so the setBean function fimply does not do anything in this case :)
What you are also missing is this line
addressBinder.setBean(recipientAddress);
you declare bindings, but you never set the initial bean.
And if you simply want to clear ALL the Fields, that are bindet to your binder, this seems to work :)
private void clearForm() {
addressBinder.getFields().forEach(f -> f.clear());
}
Now I understand it. I have misunderstanding about readBean
and setBean
. In my code. I use readBean
to show the data. But I can't use removeBean
to clear fields because the bean is null.
Thank you a lot. I appreciate it. :-)