Hi Team ,
currently we have table define on xml descriptor with below definition
Table is using an empty dataContainer as below
inside controller
I tried many trials to inject *
dataContainer then getMutableitems().add()
then append my collected items from service call , but it is not working although the table columns is filled up And also I have generated column which is LinkButton which is opening details for the selected record
my solution -> that is currently working but with strange behavior which is some times displaying data and other time now displaying data
If dataContianer.getMutableItems().add
not called the table will not display data
And if generating columns not done also , table not displaying data also
please guide me if their is proper way to do it better , as now table not always display data
Also if table displayed data and contains only one row some times when i click on it some times x scroll bar is appearing and data is hidden below it .
Try The following first inside the loop
Request request = metadata.create(Request.class);
Request is any Entity , Which is fetched from DB
durygin
(Gleb Durygin)
January 23, 2020, 12:12pm
#5
Hello @abd.ibrahim.allam ,
If I understand correctly, you are trying to delegate the update of data in the container and in the table using the above example. For this purpose, data loaders are used on the platform.
Loaders can delegate actual loading to a function which can be provided using the setLoadDelegate() method or declaratively using the @Install annotation in the screen controller.
XML descriptor
<data readOnly="true">
<collection id="requestsDc"
class="com.company.sample.entity.Request"
view="_local">
<loader id="requestsDl"/>
</collection>
</data>
Screen controller
Using the requests.load()
method, we update the data in the table.
@LoadDataBeforeShow
public class RequestBrowse extends StandardLookup<Request> {
private List<Request> requests = new ArrayList<>();
@Inject
private CollectionLoader<Request> requestsDl;
@Install(to = "requestsDl", target = Target.DATA_LOADER)
private List<Request> requestsDlLoadDelegate(LoadContext<Request> loadContext) {
return requests;
}
private void populateRequestsTblData(List<Request> requestList) {
requests.addAll(requestList);
requestsDl.load();
}
}
You can see an example of using in documentation .
Regards,
Gleb
Hi @durygin ,
Thanks for your feedback ,
Currently after applying you suggestion regarding table dataloader below is updates code snippet
fetching requests List using button that calls back end service to fetch them
using dataloader
return loaded list -
Issue
Still table not populating data without adding generated columns
dataloader
fixed the issue related to unstable data display , but i was expecting to have all the data auto displayed inside the table and for only Linkbutton , will be done using generated column
waiting for your feedback.
durygin
(Gleb Durygin)
January 27, 2020, 7:25am
#8
Hello @abd.ibrahim.allam ,
Could you send a test project or full code of screen controller and XML descriptor?
Regards,
Gleb
Hi @durygin ,
thanks for your response , below is screenshots from my screen controller and xml descriptor
xml descriptor
screen display
current behavior , as you can see from the screenshot , that request number is different which means different data is loaded , but for the reset of the table columns it is same as first row and it is duplicated,
Trials done till now
1- tried to change Label
and make it LinkButton
issue is still their
2- tried to create each column separated using foreach
for each column instead of iterating using foreach
once for all columns
3- tried to created Label
inside generated column instead of calling UIUtil
which his responsible for creating some components
Your urgent support regarding the situation is highly appreciated
Thanks
durygin
(Gleb Durygin)
February 12, 2020, 6:11am
#10
Hi @abd.ibrahim.allam ,
Could you share the code using snippets? It will be difficult for me to reproduce your case with so many screenshots.
You can find how to format the code on the forum from this topic .
Regards,
Gleb
Hi @durygin ,
Thanks for your response , sorry for screen shots , as the code is workspace and i was not able to copy it.
Below is the xml descriptor and controller as requested
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
caption="msg://request-filter-caption"
messagesPack="com.company.vp.web.request">
<data readOnly="true">
<collection id="requestsDc" class="com.company.vp.workflow.Request" view="_local">
<loader id="requestsDl"/>
</collection>
</data>
<layout spacing="true">
<split id="mainSplit" width="100%" stylename="borderless"
maxSplitPosition="90%"
orientation="horizontal"
pos="840px"
settingsEnabled="false">
<vbox id="leftSection" width="90%" height="100%" caption="msg://requests" align="TOP_LEFT">
<table id="requestsTable" visible="false"
settingsEnabled="false"
showSelection="false"
dataContainer="requestsDc"
height="100%"
width="100%">
<columns>
<column id="requestNumber"/>
<column id="subjectDisplayName"/>
<column id="requestStatusDescription"/>
<column id="submissionDate"/>
<column id="requestKind"/>
<column id="status" caption="msg://request-filter-status"/>
</columns>
</table>
</vbox>
<vbox id="rightSection" width="330px" align="TOP_RIGHT" spacing="true">
<button id="showFilterBtn" align="TOP_RIGHT" icon="font-icon:FILTER" caption="mainMsg://actions.filter"/>
<vbox id="rightSectionContainer" visible="false">
<scrollBox id="filterSB" width="100%" height="500px">
<groupBox caption="msg://filter-chx" id="filter" spacing="true" stylename="light" collapsable="true">
<hbox id="submittedByMeBox" spacing="true">
<label value="msg://request-filter-submitted-by-me" width="150px" stylename="bold" align="MIDDLE_LEFT"/>
<checkBox id="submittedByMe"/>
</hbox>
<hbox id="appproverBox" spacing="true">
<label value="msg://request-filter-approver" width="150px" stylename="bold" align="MIDDLE_LEFT"/>
<checkBox id="appproverChk"/>
</hbox>
<hbox id="notifierBox" spacing="true">
<label value="msg://request-filter-notifier" width="150px" stylename="bold" align="MIDDLE_LEFT"/>
<checkBox id="notifierChk"/>
</hbox>
<hbox id="behalfBox" spacing="true">
<label value="msg://request-filter-behalf-me" width="150px" stylename="bold" align="MIDDLE_LEFT"/>
<checkBox id="behalfMeChk"/>
</hbox>
</groupBox>
<groupBox caption="msg://request-criteria" spacing="true" stylename="light" collapsable="true">
<hbox id="requestNumberBox" spacing="true">
<label value="msg://request-filter-request-number" width="120px" stylename="bold" align="MIDDLE_LEFT"/>
<textField id="requestNumberFld" width="180px"/>
</hbox>
<hbox id="requestKindBox" spacing="true">
<label value="msg://request-filter-request-kind" width="120px" stylename="bold" align="MIDDLE_LEFT"/>
<lookupField id="requestKindFilterLKP" width="180px"/>
</hbox>
<hbox id="statusBox" spacing="true">
<label value="msg://request-filter-request-status" width="120px" stylename="bold" align="MIDDLE_LEFT"/>
<lookupField id="requestStatusFilterLKP" width="180px"/>
</hbox>
</groupBox>
<groupBox caption="msg://request-dates-filter" spacing="true" stylename="light" collapsable="true">
<hbox spacing="true">
<label value="msg://request-filter-request-submission-date" width="120px" stylename="bold" align="MIDDLE_LEFT"/>
<dateField dateFormat="dd/MM/yyyy" id="requestSubmissionFromFld" width="180px"/>
</hbox>
<hbox spacing="true">
<label value="msg://request-filter-request-submission-to-date" width="120px" stylename="bold" align="MIDDLE_LEFT"/>
<dateField dateFormat="dd/MM/yyyy" id="requestSubmissionToFld" width="180px"/>
</hbox>
<hbox spacing="true">
<label value="msg://request-filter-request-closer-date" width="120px" stylename="bold" align="MIDDLE_LEFT"/>
<dateField dateFormat="dd/MM/yyyy" id="requestClosedFromFld" width="180px"/>
</hbox>
<hbox spacing="true">
<label value="msg://request-filter-request-closer-to-date" width="120px" stylename="bold" align="MIDDLE_LEFT"/>
<dateField dateFormat="dd/MM/yyyy" id="requestClosedToFld" width="180px"/>
</hbox>
</groupBox>
<label id="spacer"/>
<button id="refreshBtn" align="MIDDLE_RIGHT" caption="mainMsg://actions.Refresh" stylename="friendly" icon="font-icon:SEARCH"/>
</scrollBox>
</vbox>
</vbox>
</split>
</layout>
</window>
package com.company.vp.web.request;
import com.company.vp.entity.VPayUser;
import com.company.vp.service.WorkflowService;
import com.company.vp.web.mixin.Constants;
import com.company.vp.web.mixin.ScreenParamOptions;
import com.company.vp.web.utils.UIUtil;
import com.company.vp.workflow.Request;
import com.company.vp.workflow.RequestKind;
import com.company.vp.workflow.RequestSearchCriteria;
import com.company.vp.workflow.RequestStatus;
import com.haulmont.bali.util.ParamsMap;
import com.haulmont.cuba.core.global.LoadContext;
import com.haulmont.cuba.gui.ScreenBuilders;
import com.haulmont.cuba.gui.UiComponents;
import com.haulmont.cuba.gui.components.*;
import com.haulmont.cuba.gui.components.actions.BaseAction;
import com.haulmont.cuba.gui.model.CollectionContainer;
import com.haulmont.cuba.gui.model.CollectionLoader;
import com.haulmont.cuba.gui.screen.*;
import com.haulmont.cuba.security.global.UserSession;
import javax.inject.Inject;
import java.text.SimpleDateFormat;
import java.util.*;
@UiController("vp_RequestsFilter")
@UiDescriptor("requests-filter.xml")
public class RequestsFilter extends Screen {
@Inject
private WorkflowService workflowService;
@Inject
private UserSession userSession;
@Inject
private CheckBox submittedByMe;
@Inject
private CheckBox notifierChk;
@Inject
private CheckBox behalfMeChk;
@Inject
private CheckBox appproverChk;
@Inject
private TextField<String> requestNumberFld;
@Inject
private DateField<Date> requestSubmissionToFld;
@Inject
private DateField<Date> requestSubmissionFromFld;
@Inject
private DateField<Date> requestClosedFromFld;
@Inject
private DateField<Date> requestClosedToFld;
@Inject
private LookupField<RequestStatus> requestStatusFilterLKP;
@Inject
private LookupField<RequestKind> requestKindFilterLKP;
@Inject
private Table<Request> requestsTable;
@Inject
private CollectionLoader<Request> requestsDl;
@Inject
private UiComponents uiComponents;
@Inject
private ScreenBuilders screenBuilders;
@Inject
private MessageBundle messageBundle;
@Inject
private VBoxLayout rightSectionContainer;
private List<Request> requests;
@Subscribe
public void onBeforeShow(BeforeShowEvent event) {
requestKindFilterLKP.setOptionsEnum(RequestKind.class);
requestStatusFilterLKP.setOptionsEnum(RequestStatus.class);
}
@Subscribe("showFilterBtn")
public void onShowFilterBtnClick(Button.ClickEvent event) {
if (rightSectionContainer.isVisible()) {
rightSectionContainer.setVisible(false);
} else {
rightSectionContainer.setVisible(true);
}
}
@Subscribe("refreshBtn")
public void onRefreshBtnClick(Button.ClickEvent event) {
VPayUser user = (VPayUser) userSession.getUser();
UUID userId = user.getId();
String requestNumber = requestNumberFld.getValue();
RequestKind kind = requestKindFilterLKP.getValue();
RequestStatus status = requestStatusFilterLKP.getValue();
Date requestSubmissionFrom = requestSubmissionFromFld.getValue();
Date requestSubmissionTo = requestSubmissionToFld.getValue();
Date requestClosedFrom = requestClosedFromFld.getValue();
Date requestClosedTo = requestClosedToFld.getValue();
requests = new ArrayList<>(workflowService.searchRequests(getSearchCriteria(), userId, requestNumber, kind, status,
requestSubmissionFrom, requestSubmissionTo, requestClosedFrom, requestClosedTo));
populateRequestsTblData(requests);
}
@Install(to = "requestsDl", target = Target.DATA_LOADER)
private List<Request> requestsDlLoadDelegate(LoadContext<Request> loadContext) {
return requests;
}
private List<RequestSearchCriteria> getSearchCriteria() {
List<RequestSearchCriteria> criteria = new ArrayList<>();
if (submittedByMe.getValue()) {
criteria.add(RequestSearchCriteria.SUBMITTER);
}
if (appproverChk.getValue()) {
criteria.add(RequestSearchCriteria.APPROVER);
}
if (notifierChk.getValue()) {
criteria.add(RequestSearchCriteria.NOTIFIER);
}
if (behalfMeChk.getValue()) {
criteria.add(RequestSearchCriteria.BEHALF_OF_ME);
}
return criteria;
}
private void populateRequestsTblData(List<Request> requests) {
requestsDl.load();
requestsTable.setVisible(false);
requests.forEach(request -> {
requestsTable.addGeneratedColumn("requestNumber", entity -> {
return buildActionButton(entity);
});
requestsTable.addGeneratedColumn("subjectDisplayName", entity -> {
return UIUtil.createLbl(request.getSubjectDisplayName());
});
requestsTable.addGeneratedColumn("requestStatusDescription", entity -> {
return UIUtil.createLbl(request.getRequestStatusDescription());
});
requestsTable.addGeneratedColumn("submissionDate", entity -> {
return UIUtil.createLbl(formatDate(request.getSubmissionDate()));
});
requestsTable.addGeneratedColumn("requestKind", entity -> {
return UIUtil.createLbl(request.getRequestKind());
});
requestsTable.addGeneratedColumn("status", entity -> {
return UIUtil.createLbl(request.getStatus());
});
});
requestsTable.setVisible(true);
}
private LinkButton buildActionButton(Request request) {
LinkButton link = uiComponents.create(LinkButton.class);
link.setId(String.valueOf(request.getId()));
link.setAlignment(Component.Alignment.MIDDLE_CENTER);
link.setCaption(request.getRequestNumber());
link.setDescription(messageBundle.getMessage("press-me-for-details"));
link.setFrame(getWindow().getFrame());
link.setAction(new BaseAction(Constants.GENERAL_ACTION_ID)
.withHandler(e -> {
screenBuilders.screen(this)
.withLaunchMode(OpenMode.DIALOG)
.withOptions(new ScreenParamOptions(ParamsMap.of(Constants.REQUEST_PARAM, request.getId())))
.withScreenClass(RequestDetails.class).build().show();
}));
return link;
}
private String formatDate(Date date) {
if (Objects.nonNull(date)) {
SimpleDateFormat formatter = new SimpleDateFormat(Constants.DATE_TIME_FORMAT);
return formatter.format(date);
}
return null;
}
}
Thanks for your fast response
durygin
(Gleb Durygin)
February 13, 2020, 8:00am
#13
Hello @abd.ibrahim.allam ,
I can’t reproduce your problem using code snippets. Could you share the test project where the case can be reproduced? Why do you turn off then turn on the table display in populateRequestsTblData
function?
Regards,
Gleb
Hi @durygin ,
This is production system , I may not be able to provide sample project for the same ,
can we investigate that issue together with the provided snippets
For displaying Table may be this is mistaken code that i forget to remove while trying ,
I just want from your side like high level guidance if i’m doing any thing wrong while populating table data
durygin
(Gleb Durygin)
February 13, 2020, 9:15am
#16
@abd.ibrahim.allam , based on code snippets, I can suggest you simplify your implementation a bit and maybe you will find the source of your problem:
To make the column requestNumber
generated, you can install a column generator as shown in the following snippet:
@Install(to = "requestsTable.requestNumber", subject = "columnGenerator")
private Component requestsTableRequestNumberColumnGenerator(Request request) {
LinkButton link = uiComponents.create(LinkButton.class);
link.setId(String.valueOf(request.getId()));
link.setAlignment(Component.Alignment.MIDDLE_CENTER);
link.setCaption(request.getRequestNumber());
link.setDescription(messageBundle.getMessage("press-me-for-details"));
link.setFrame(getWindow().getFrame());
link.setAction(new BaseAction(Constants.GENERAL_ACTION_ID)
.withHandler(e -> {
screenBuilders.screen(this)
.withLaunchMode(OpenMode.DIALOG)
.withOptions(new ScreenParamOptions(ParamsMap.of(Constants.REQUEST_PARAM, request.getId())))
.withScreenClass(RequestDetails.class).build().show();
}));
return link;
}
You can replace the call to the populateRequestsTblData
function with a call to reportsDl.load()
function. And this should work, even with generated columns.
Set the visible
attribute for requestsTable
to true
value if you do not use it elsewhere.
What reports should be shown at the initial opening of the screen? With the current implementation, the table will initially be empty. Table will update the data at the click on Refresh
button.
Regards,
Gleb
Hi @durygin ,
Thanks for your response , let me try your suggestion and return back to you .
Hi @durygin ,
below is code now for my controller that is working fine with me ,
I tried your solution regarding only loading requestDl.load()
to load table data without adding
GeneratedColumns
for each columns but it is not working
below is my code controller code , that is working fine for displaying data correctly .
import com.company.vp.entity.VPayUser;
import com.company.vp.service.WorkflowService;
import com.company.vp.web.mixin.Constants;
import com.company.vp.web.mixin.ScreenParamOptions;
import com.company.vp.web.utils.UIUtil;
import com.company.vp.workflow.Request;
import com.company.vp.workflow.RequestKind;
import com.company.vp.workflow.RequestSearchCriteria;
import com.company.vp.workflow.RequestStatus;
import com.google.common.base.CaseFormat;
import com.haulmont.bali.util.ParamsMap;
import com.haulmont.cuba.core.global.LoadContext;
import com.haulmont.cuba.gui.ScreenBuilders;
import com.haulmont.cuba.gui.UiComponents;
import com.haulmont.cuba.gui.components.*;
import com.haulmont.cuba.gui.components.actions.BaseAction;
import com.haulmont.cuba.gui.model.CollectionContainer;
import com.haulmont.cuba.gui.model.CollectionLoader;
import com.haulmont.cuba.gui.screen.*;
import com.haulmont.cuba.security.global.UserSession;
import javax.inject.Inject;
import java.text.SimpleDateFormat;
import java.util.*;
@UiController("vp_RequestsFilter")
@UiDescriptor("requests-filter.xml")
public class RequestsFilter extends Screen {
@Inject
private WorkflowService workflowService;
@Inject
private UserSession userSession;
@Inject
private CheckBox submittedByMe;
@Inject
private CheckBox notifierChk;
@Inject
private CheckBox behalfMeChk;
@Inject
private CheckBox appproverChk;
@Inject
private TextField<String> requestNumberFld;
@Inject
private DateField<Date> requestSubmissionToFld;
@Inject
private DateField<Date> requestSubmissionFromFld;
@Inject
private DateField<Date> requestClosedFromFld;
@Inject
private DateField<Date> requestClosedToFld;
@Inject
private LookupField<RequestStatus> requestStatusFilterLKP;
@Inject
private LookupField<RequestKind> requestKindFilterLKP;
@Inject
private Table<Request> requestsTable;
@Inject
private CollectionLoader<Request> requestsDl;
@Inject
private UiComponents uiComponents;
@Inject
private ScreenBuilders screenBuilders;
@Inject
private MessageBundle messageBundle;
@Inject
private VBoxLayout rightSectionContainer;
private List<Request> requests;
@Subscribe
public void onBeforeShow(BeforeShowEvent event) {
requestKindFilterLKP.setOptionsEnum(RequestKind.class);
requestStatusFilterLKP.setOptionsEnum(RequestStatus.class);
}
@Subscribe("showFilterBtn")
public void onShowFilterBtnClick(Button.ClickEvent event) {
if (rightSectionContainer.isVisible()) {
rightSectionContainer.setVisible(false);
} else {
rightSectionContainer.setVisible(true);
}
}
@Subscribe("refreshBtn")
public void onRefreshBtnClick(Button.ClickEvent event) {
VPayUser user = (VPayUser) userSession.getUser();
UUID userId = user.getId();
String requestNumber = requestNumberFld.getValue();
RequestKind kind = requestKindFilterLKP.getValue();
RequestStatus status = requestStatusFilterLKP.getValue();
Date requestSubmissionFrom = requestSubmissionFromFld.getValue();
Date requestSubmissionTo = requestSubmissionToFld.getValue();
Date requestClosedFrom = requestClosedFromFld.getValue();
Date requestClosedTo = requestClosedToFld.getValue();
requests = new ArrayList<>(workflowService.searchRequests(getSearchCriteria(), userId, requestNumber, kind, status,
requestSubmissionFrom, requestSubmissionTo, requestClosedFrom, requestClosedTo));
requestsDl.load();
}
@Install(to = "requestsDl", target = Target.DATA_LOADER)
private List<Request> requestsDlLoadDelegate(LoadContext<Request> loadContext) {
return requests;
}
private List<RequestSearchCriteria> getSearchCriteria() {
List<RequestSearchCriteria> criteria = new ArrayList<>();
if (submittedByMe.getValue()) {
criteria.add(RequestSearchCriteria.SUBMITTER);
}
if (appproverChk.getValue()) {
criteria.add(RequestSearchCriteria.APPROVER);
}
if (notifierChk.getValue()) {
criteria.add(RequestSearchCriteria.NOTIFIER);
}
if (behalfMeChk.getValue()) {
criteria.add(RequestSearchCriteria.BEHALF_OF_ME);
}
return criteria;
}
@Install(to = "requestsTable.requestNumber", subject = "columnGenerator")
private Component requestsTableRequestNumberColumnGenerator(Request request) {
LinkButton link = uiComponents.create(LinkButton.class);
link.setId(String.valueOf(request.getId()));
link.setAlignment(Component.Alignment.MIDDLE_CENTER);
link.setCaption(request.getRequestNumber());
link.setDescription(messageBundle.getMessage("press-me-for-details"));
link.setFrame(getWindow().getFrame());
link.setAction(new BaseAction(Constants.GENERAL_ACTION_ID)
.withHandler(e -> {
screenBuilders.screen(this)
.withLaunchMode(OpenMode.DIALOG)
.withOptions(new ScreenParamOptions(ParamsMap.of(Constants.REQUEST_PARAM, request.getId())))
.withScreenClass(RequestDetails.class).build().show();
}));
return link;
}
@Install(to = "requestsTable.subjectDisplayName", subject = "columnGenerator")
private Component requestsTableSubjectNameColumnGenerator(Request request) {
Label lbl = uiComponents.create(Label.class);
lbl.setAlignment(Component.Alignment.MIDDLE_LEFT);
lbl.setValue(request.getSubjectDisplayName());
return lbl;
}
@Install(to = "requestsTable.requestStatusDescription", subject = "columnGenerator")
private Component requestsTableRequestStatusDescColumnGenerator(Request request) {
Label lbl = uiComponents.create(Label.class);
lbl.setAlignment(Component.Alignment.MIDDLE_LEFT);
lbl.setValue(request.getRequestStatusDescription());
return lbl;
}
@Install(to = "requestsTable.submissionDate", subject = "columnGenerator")
private Component requestsTableRequestSubmissionDateColumnGenerator(Request request) {
Label lbl = uiComponents.create(Label.class);
lbl.setAlignment(Component.Alignment.MIDDLE_LEFT);
String date = Objects.nonNull(request.getSubmissionDate()) ? formatDate(request.getSubmissionDate()) : "";
lbl.setValue(date);
return lbl;
}
@Install(to = "requestsTable.requestKind", subject = "columnGenerator")
private Component requestsTableRequestKindColumnGenerator(Request request) {
Label lbl = uiComponents.create(Label.class);
lbl.setAlignment(Component.Alignment.MIDDLE_LEFT);
String kind = Objects.nonNull(request.getRequestKind()) ? getDisplayString(request.getRequestKind().name()) : "";
lbl.setValue(kind);
return lbl;
}
@Install(to = "requestsTable.status", subject = "columnGenerator")
private Component requestsTableRequestStatusColumnGenerator(Request request) {
Label lbl = uiComponents.create(Label.class);
lbl.setAlignment(Component.Alignment.MIDDLE_LEFT);
String status = Objects.nonNull(request.getStatus()) ? getDisplayString(request.getStatus().name()) : "";
lbl.setValue(status);
return lbl;
}
private String formatDate(Date date) {
if (Objects.nonNull(date)) {
SimpleDateFormat formatter = new SimpleDateFormat(Constants.DATE_TIME_FORMAT);
return formatter.format(date);
}
return null;
}
private String getDisplayString(String str) {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, str.replaceAll("_", " "));
}
}