Hi
I am trying to use use a ComboBox in ElementCollectionTable of Viritin add-on. Wondering how to use the container here! I am reusing the invoicer sample application of Viritin :
// List<Product> custList = facade.findAll();
// BeanItemContainer<Product> custContainer = new BeanItemContainer<>(Product.class, custList);
public static final class RowEditorModel {
ComboBox products = new ComboBox();
MTextField description = new MTextField().withFullWidth();
MTextField amount = new MTextField().withWidth("100px");
MTextField unit = new MTextField().withWidth("3em");
MTextField price = new MTextField().withWidth("3em");
}
ElementCollectionTable<InvoiceRow> invoiceRows = new ElementCollectionTable<>(
InvoiceRow.class, RowEditorModel.class);
The ComboBox shows up in the ElementCollectionTable (as attached) but didn;t find a good way to use a container to populate the ComboBox. Any help will be appreciated.
I modified the example in Viritin test case to use the related feature:
editor row instantiator . I think that should work for pretty much any use case.
The Invoicer example could indeed contain a table for products and have a combobox for existing products in the invoice row editor.
I’ll try to find some time to improve that example during the spring (and write some helpful articles about it), but I have no exact plans when. I’d be more than happy if you can write this part to the example and sure will find time to help you in this task if needed.
Hi
Sure, I can try it. For the invoice sample, I describe below where I need your help at the moment.
Here is the modified code of InvoiceForm following your ElementCollections class. I have created an Entity named Product and a Facade for the same, used ElementCollectionTable instead of ElementCollectionField, added listeners etc…as below. Now problem is, how to populate the products combobox in the ElemenetCollectionTable in this example.
[code] @ViewScoped
public class InvoiceForm extends AbstractForm {
@Inject
ContactSelector to;
@Inject
ProductFacade facade2;
DateField invoiceDate = new DateField("invoiceDate");
DateField dueDate = new DateField("dueDate");
Header total = new Header("").setHeaderLevel(3);
static AbstractElementCollection.ElementAddedListener<InvoiceRow> addedListener = new AbstractElementCollection.ElementAddedListener<InvoiceRow>() {
@Override
public void elementAdded(
AbstractElementCollection.ElementAddedEvent<InvoiceRow> e) {
Notification.show("Added row: " + e.getElement());
}
};
static AbstractElementCollection.ElementRemovedListener<InvoiceRow> removeListener = new AbstractElementCollection.ElementRemovedListener<InvoiceRow>() {
@Override
public void elementRemoved(
AbstractElementCollection.ElementRemovedEvent<InvoiceRow> e) {
Notification.show("Removed row: " + e.getElement());
}
};
public static final class RowEditorModel {
ComboBox products = new ComboBox();
MTextField description = new MTextField().withFullWidth();
MTextField amount = new MTextField().withWidth("3em");
MTextField unit = new MTextField().withWidth("3em");
MTextField price = new MTextField().withWidth("3em");
}
private final ElementCollectionTable<InvoiceRow> invoiceRows
= new ElementCollectionTable<InvoiceRow>(InvoiceRow.class,
RowEditorModel.class).withCaption("Invoice Detail").
setAllowNewElements(true).
setAllowRemovingItems(true).addElementAddedListener(addedListener).
addElementRemovedListener(removeListener);
@PostConstruct
void init() {
// Allowing null in DB, but not when modified by the UI
to.setRequired(true);
to.addValidator(new AbstractValidator("Receiver must be set") {
@Override
protected boolean isValidValue(Object value) {
return value != null;
}
@Override
public Class getType() {
return Contact.class;
}
});
invoiceRows.addValueChangeListener(e -> updateTotal());
}
@Override
protected Component createContent() {
/**
* In simple cases the editor row instance don't need to be configured
* or it can be instantiated automatically with empty parameter
* constructor. This would work here as well, but as an example lets
* override the instantiation strategy, where in real life you could
* e.g. populate options to selects from your backend.
*/
invoiceRows.setEditorInstantiator(
new AbstractElementCollection.Instantiator<InvoiceRow>() {
@Override
public InvoiceRow create() {
InvoiceRow addressRow = new InvoiceRow();
// populate manually.
return addressRow;
}
});
return new MVerticalLayout(
new MHorizontalLayout(getToolbar()).add(total,
Alignment.MIDDLE_RIGHT)
.withFullWidth(),
new MVerticalLayout(
to,
new MHorizontalLayout(invoiceDate, dueDate),
invoiceRows
)
);
}
void updateTotal() {
try {
total.setText(getEntity().getTotal() + " €");
} catch (Exception e) {
total.setText("--");
}
}
@Override
public Window openInModalPopup() {
final Window p = super.openInModalPopup();
p.setWidth("80%");
p.setHeight("95%");
return p;
}
}
[/code]I tried to populate the products comboBox using the following codes under: setEditorInstantiator (Populate Manually…). but no good result…
invoiceRows.getTable().setTableFieldFactory(new DefaultFieldFactory() {
@Override
public Field createField(Container container, Object itemId,
Object propertyId, Component uiContext) {
if ("products".equals(propertyId)) {
List<Product> prodList = facade2.findAll();
BeanItemContainer<Product> prodContainer = new BeanItemContainer<>(Product.class, prodList);
ComboBox products = new ComboBox();
products.setContainerDataSource(prodContainer);
return products;
}
return super.createField(container, itemId, propertyId, uiContext);
}
});
Hi matti
I have send you the pull request with the product table, facade, product view and form files as requested. Please let me know if you have received them correctly.
Meanwhile, I order to bring lightening fast speed of development in vaadin, I started writing freemarker template to use with EntityExpander in netbeans (I am inspired from one of your webinar on this).
Good effort with EntityExpander! If you create good templates, I can commit them to the EntityExpander repository and ask Geertjan to publish a new version. Those code generators are really valueable, especially in the beginning of the projects. There is also similar [Viritin templates for IntelliJ]
(https://github.com/viritin/viritin/issues/63).
I’ll spend now a moment with jpa-invoicer, thanks again for your contributions!
Hi Matti,
I have send you two freetext marker template (one for View and another for Form files) at GitHub as first draft. I need your help in few places there in order to complete it which may work in may cases to different developers and it will be a great idea to publish them in netbeans. After these two templates are done, I shall work on few more template to address some other application in vaadin user interfaces.