Data in the dynamically created TableColumn

Hi
I have s table UI where I have 2 columns coming from an Entity, say Colour. I have created few other columns dynamically based on the contents from another Entity, say size S, M, XL, XXL etc.

Here is the code I have to create the size columns:


public void onRefreshSizeColor(Component source) {
        for (ArticleSize size : articleSizeDs.getItems()) {
            salesOrderSizeColourTable.addGeneratedColumn(size.getName(), entity -> {
                Label label = componentsFactory.createComponent(Label.class);
                return label;
            });
        }

Now, I want to insert some rows in this table “salesOrderSizeColourTable” and populate with quantities in different size columns that has been created dynamically and that should be persisted later. Any help is appreciated.

1 Like

To insert data, I have following and it adds new row in the table. The columns Article, Colour are editable:


   SalesOrderSizeColour line = metadata.create(SalesOrderSizeColour.class);
        line.setSalesOrder(salesOrderDs.getItem());
        salesOrderSizeColourDs.addItem(line);

I have set those The remaining question is:

  • How can I turn the dynamically created columns Editable?
  • how can I manipulate data in those columns dynamically created columns (display from entity, persist etc.)

- How can I turn the dynamically created columns Editable?

You can create TextField instead of Label in your column generator.

- how can I manipulate data in those columns dynamically created columns (display from entity, persist etc.)

To display, set the value of the TextFields.
To persist, add a ValueListener to the TextField, accumulate changes somehow (for example in a list of persistent entities), and add these entities to the screen commit in a BeforeCommitListener of DsContext.

Consider also a “less dynamic” approach with standard persistent and non-persistent entities.

Hi
Thanks. I have used TextField as follows but it is still not editable -


        for (ArticleSize size : articleSizeDs.getItems()) {
            salesOrderSizeColourTable.addGeneratedColumn(size.getName(), entity -> {
                TextField textField = componentsFactory.createComponent(TextField.class);
                textField.setEditable(true);
                textField.setEnabled(true);
                return textField;
            });
 }

Could you attach a small project illustrating the problem?

Hi
I have realized what went wrong while I went to complete the sample project to illustrate the problem. It’s working perfectly. I am going to ask my 2nd part of the question i.e. How do I bind the dynamically created columns with the CollectionDatasource?

I have the following fields in the Entity/CollectionDatasource: Article, Colour, Quantity.
The data in entity looks like:

Article | Colour | Size | Quantity

first two fields are generated as column and populated as usual. but As I have several records for Article + Colour by size, i want to populate the quantity per size in dynamically created columns (list of size is coming from another entity which might vary based on selection).

Article | Colour | sizeS | SizeM | SizeL | SizeXL

Shirt Blue 10 15 6 3

Manipulating the row values to columns might be a solution to visualize the data for which an Array can be a solution. How can I use a CUBA table where the datasource is not directly created from the database table but something like array? Please also let me know if there is any better approach than using an array in between database and the table to display and persist.

How can I use a CUBA table where the datasource is not directly created from the database table but something like array?

You can visualize any data in the Table component if you create a non-persistent entity and add its instances to the datasource linked to the table. Set refreshMode=“NEVER” and allowCommit=“false” attributes for the table and use includeItem() method for adding entitiy instances to the datasource.

Let me explain that I have two purposes:

  1. There is no definite number of columns I’ll have for this. It is totally depending on number of rows of specific dataset. Therefore, adding a pre-defined entity may limit the number of columns that is needed. Do you mean to create the non-persistent entity on the fly?

  2. I need the manipulated data to be saved back to database table, how can I do that while using non-persistent entity to show the data?
    Thanks for your help.

Hi
I was looking at the code that I developed in java swing many years ago. I need something similar in terms of functionality. I hope there is a way achieving the same in CUBA.

When displaying data from Database:


  for (int i = 0; i < NRows; i++) {
                    jCat = (String) rowData<i>[0];
                     jId = (Integer) rowData<i>[1];
                     for (int c = firstFloorCol; c < floorHorizonLastCol; c++) {
                                    fId = table1.getColumnModel().getColumn(c).getHeaderValue().toString();
                                    rate = (Double) rowData<i>[c];
                                     if(fId != null && fId.length()<6){  
                                                   stmt.addBatch("INSERT INTO DcmSubContJobRateD (JobRateId, SubContJobId, Rate, JobCategory, FloorNo) "
                                                + "VALUES (" + docNumber + ", '" + jId + "'," + rate + ",'" + jCat + "','" + fId + "')");
                                   }
                    }
}
</i></i></i>


Loading existing data from database to UI Table


while (rs.next()) {
rowData[j][0] = rs.getString(1);
jId = rs.getInt(2);
rowData[j][1] = rs.getInt(2);
rowData[j][2] = rs.getString(3);
rowData[j][3] = rs.getString(4);
//Load Floors as columns
if (!actionType.equalsIgnoreCase("new")) {
sql = "SELECT f.FloorNo, ISNULL(d.Rate,0) FROM DcmFloors f LEFT OUTER JOIN DcmSubContJobRateD d ON (f.FloorNo=d.FloorNo) "
+ "AND (d.JobRateId='" + mJobRateId.getText() + "')  AND (d.JobCategory='" + jobCategory + "') AND (d.SubContJobId=" + jId + ")";
Statement stmt2 = dbConnection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs2 = stmt2.executeQuery(sql);
int firstFloorCol = 4;
if (rs2.next()) {
rs2.beforeFirst();
while (rs2.next()) {
fId = rs2.getString(1);
rate = rs2.getDouble(2);
for (int i = firstFloorCol; i < floorHorizonLastCol; i++) {
floorColumn = table1.getColumnModel().getColumn(i).getHeaderValue().toString();
if (fId.equalsIgnoreCase(floorColumn)) {
rowData[j]<i> = new Double(rate);
break;
}
}
}
} else {
for (int i = firstFloorCol; i < floorHorizonLastCol; i++) {
rowData[j]<i> = new Double(0);
}
rowData[j][floorHorizonLastCol] = new Double(0);
}
rs2.close();
stmt2.close();
}
j++;
}
</i></i>

1) There is no definite number of columns I’ll have for this.

You can try using KeyValueEntity and KeyValueCollectionDatasourceImpl introduced in the latest platform release. They are intended for displaying arbitrary sets of values not known at design time. See JavaDocs for KeyValueEntity class and the following code example:


KeyValueCollectionDatasourceImpl ds = new DsBuilder().buildCollectionDatasource(KeyValueCollectionDatasourceImpl.class);
ds.addProperty("prop1").addProperty("prop2").addProperty("prop3");

KeyValueEntity entity;

entity = new KeyValueEntity();
entity.setValue("prop1", "val1");
entity.setValue("prop2", "val2");
entity.setValue("prop3", "val3");
ds.includeItem(entity);

entity = new KeyValueEntity();
entity.setValue("prop1", "val11");
entity.setValue("prop2", "val21");
entity.setValue("prop4", "val31");
ds.includeItem(entity);

Table table = componentsFactory.createComponent(Table.class));
table.setWidth("100%");
table.setHeight("100%");
table.setDatasource(ds);
table.setColumnCaption("prop1", "Property 1");
table.setColumnCaption("prop2", "Property 2");
table.setColumnCaption("prop3", "Property 3");

add(table);

2) I need the manipulated data to be saved back to database table, how can I do that while using non-persistent entity to show the data?

You can transfer data back to some persistent entity and save it through DataManager or your own service.

Thank you Konstantin.
Now I can dynamically create the columns using your code like how we could create using standard Column creation mechanism. Now, having an error when inserting some records:

and Here is my code:


for (SalesOrderLine soLine : linesDs.getItems()) {
            if (soLine.getArticle() != null) {
                for (ArticleColour articleColour : articleColoursDs.getItems()) {
                    showNotification("here",NotificationType.HUMANIZED);
                        KeyValueEntity entity = new KeyValueEntity();
                        entity.setValue("salesOrder", salesOrderDs.getItem());
                        entity.setValue("article", soLine.getArticle());
                        entity.setValue("colour", articleColour.getColourName());
                        ds.includeItem(entity);
                }
            }
        }

getting the following error.


java.lang.ClassCastException: com.haulmont.cuba.core.entity.KeyValueEntity cannot be cast to com.company.gms.entity.SalesOrderSizeColour
	at com.company.gms.gui.salesorder.SalesorderEdit$$Lambda$141/1081272608.generateCell(Unknown Source)
	at com.haulmont.cuba.web.gui.components.WebAbstractTable$4.generateCell(WebAbstractTable.java:1417)
	at com.vaadin.ui.Table.parseItemIdToCells(Table.java:2402)
	at com.vaadin.ui.Table.getVisibleCellsNoCache(Table.java:2275)
	at com.vaadin.ui.Table.refreshRenderedCells(Table.java:1778)
	at com.vaadin.ui.Table.refreshRowCache(Table.java:2729)
	at com.vaadin.ui.Table.containerItemSetChange(Table.java:4666)
	at com.vaadin.data.util.ContainerOrderedWrapper$PiggybackListener.containerItemSetChange(ContainerOrderedWrapper.java:700)
	at com.haulmont.cuba.web.gui.data.CollectionDsWrapper.fireItemSetChanged(CollectionDsWrapper.java:114)
	at com.haulmont.cuba.web.gui.data.CollectionDsWrapper$ContainerDatasourceCollectionChangeListener.collectionChanged(CollectionDsWrapper.java:262)
	at com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener.collectionChanged(WeakCollectionChangeListener.java:43)
	at com.haulmont.cuba.gui.data.impl.AbstractCollectionDatasource.fireCollectionChanged(AbstractCollectionDatasource.java:364)
	at com.haulmont.cuba.gui.data.impl.CollectionDatasourceImpl.includeItem(CollectionDatasourceImpl.java:356)
	at com.haulmont.cuba.gui.data.impl.KeyValueCollectionDatasourceImpl.includeItem(KeyValueCollectionDatasourceImpl.java:57)
	at com.company.gms.gui.salesorder.SalesorderEdit.addQuantityByColour(SalesorderEdit.java:275)
	at com.company.gms.gui.salesorder.SalesorderEdit.onRefreshSizeColor(SalesorderEdit.java:198)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.haulmont.cuba.gui.xml.DeclarativeAction.actionPerform(DeclarativeAction.java:86)
	at com.haulmont.cuba.web.gui.components.WebButton.performAction(WebButton.java:53)
	at com.haulmont.cuba.web.gui.components.WebButton$1.buttonClick(WebButton.java:44)
	at sun.reflect.GeneratedMethodAccessor276.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:198)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:161)
	at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1008)
	at com.vaadin.ui.Button.fireClick(Button.java:377)
	at com.haulmont.cuba.web.toolkit.ui.CubaButton.fireClick(CubaButton.java:56)
	at com.vaadin.ui.Button$1.click(Button.java:54)
	at sun.reflect.GeneratedMethodAccessor275.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:158)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:118)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:414)
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:79)
	at com.haulmont.cuba.web.sys.CubaVaadinServletService$CubaUidlRequestHandler.lambda$synchronizedHandleRequest$82(CubaVaadinServletService.java:306)
	at com.haulmont.cuba.web.sys.CubaVaadinServletService$CubaUidlRequestHandler$$Lambda$40/1217772279.call(Unknown Source)
	at com.haulmont.cuba.web.sys.CubaVaadinServletService.withUserSession(CubaVaadinServletService.java:187)
	at com.haulmont.cuba.web.sys.CubaVaadinServletService$CubaUidlRequestHandler.synchronizedHandleRequest(CubaVaadinServletService.java:306)
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1409)
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:369)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:242)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:165)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.handleNotFiltered(CubaHttpFilter.java:110)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:97)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1526)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1482)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)

HI Konstantin,
My effort to use KeyValueEntity didn’t work as explained above. Is there any other thoughts that can be applied here? Thank you in advance.

Mortoza

I’m still waiting for a workable solution for this problem. Any help is appreciated.

Is it not possible in CUBA?

Please see my answer above:

If it does not help, you can always bypass CUBA UI mechanisms and use Vaadin components directly, see Working with Vaadin Components - CUBA Platform. Developer’s Manual

Hi,
Can you give an example for Cuba 7?
Regards,
-n