How to disable sorting on Primefaces lazy datatable? - primefaces

I have a datatable with lazy data model and pagination. I want to disable default sorting when I click on "search" button and enable it again when I click on "display" button. So didn't put "sortBy" in my xhtml file and instead, I set it dynamically in my backing bean.
Everything works properly until I click on the header to flip sort order between descending and ascending. It means the "search" button disables the sorting and "display" button enables it correctly if I don't click on the header. But when I click on the header and then click the "search" button, in load funciton of LazyDataModel, value of the argument sortField is "date" and the datatable will be sorted by date though the "date" column is not colored apparently!!
This is my datatable:
<h:form id="contents-form">
...
<p:dataTable id="tbl" widgetVar="tbl" var="msg" value="#{homeController.messagesModel}" lazy="true"
currentPageReportTemplate="سطر {startRecord}-{endRecord} از {totalRecords}"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
paginator="true" rows="10" rowsPerPageTemplate="5,10,15"
emptyMessage="هیچ پیامکی وجود ندارد."
selection="#{homeController.selectedMessages}" rowSelectMode="checkbox"
rowKey="#{msg.id}" filteredValue="#{homeController.filteredMessage}"
editable="true" editMode="cell"
style="width:100%" dir="rtl">
<f:facet name="header">
<p:commandButton value="خروجی" action="#{homeController.prepareExport}" icon="fa fa-save"
update="export-dlg-box" oncomplete="PF('exportDlgBox').show()"/>
<p:commandButton value="واژگان" action="#{homeController.showListTermsChart}"
icon="fa fa-bar-chart" update="contents-form chart-form msgs"
oncomplete="PF('chartDlgBox').show()"/>
</f:facet>
<p:ajax event="cellEdit" listener="#{homeController.onCellEdit}" oncomplete="updateDescFilter()"/>
<p:column selectionMode="multiple" style="width:16px;text-align:center"/>
<p:column headerText="فرستنده" style="width:100px" filterBy="#{msg.sender.number}"
sortBy="#{msg.sender.number}">
<p:commandLink action="#{homeController.setPhoneNumToShow(msg.sender)}" update="phone-form"
oncomplete="PF('phoneDlgBox').show()" styleClass="simple-command-link">
<h:outputText value="#{msg.sender.number}"/>
</p:commandLink>
</p:column>
<p:column headerText="گیرنده" style="width:100px" filterBy="#{msg.receiver.number}"
sortBy="#{msg.receiver.number}">
<p:commandLink action="#{homeController.setPhoneNumToShow(msg.receiver)}" update="phone-form"
oncomplete="PF('phoneDlgBox').show()" styleClass="simple-command-link">
<h:outputText value="#{msg.receiver.number}"/>
</p:commandLink>
</p:column>
<p:column headerText="متن" sortBy="#{msg.text}">
<h:outputText value="#{msg.getTrimmedText()}"/>
</p:column>
<p:column headerText="زمان" style="width:100px" filterBy="#{msg.date}" sortBy="#{msg.date}">
<f:facet name="filter">
<p:calendar pattern="yyyy-MM-dd">
<p:ajax event="dateSelect" oncomplete="PF('tbl').filter()" update="tbl"/>
</p:calendar>
</f:facet>
<h:outputText value="#{msg.getJalaliDate()}"/>
</p:column>
<p:column headerText="منبع" style="width:70px" filterBy="#{msg.source}" sortBy="#{msg.source}">
<f:facet name="filter">
<p:selectOneMenu onchange="PF('tbl').filter()" style="width:30px; direction:ltr">
<f:selectItem itemLabel="همه" itemValue="#{null}" noSelectionOption="true"/>
<f:selectItems value="#{homeController.sources}" var="source"
itemValue="#{source}" itemLabel="#{source}"/>
</p:selectOneMenu>
</f:facet>
<h:outputText value="#{msg.source}"/>
</p:column>
<p:column headerText="توضیح" style="width:70px" filterBy="#{msg.description}"
sortBy="#{msg.description}">
<f:facet name="filter">
<p:selectOneMenu id="desc-filter-select" onchange="PF('tbl').filter()"
style="width:30px; direction:ltr">
<f:selectItem itemLabel="همه" itemValue="#{null}" noSelectionOption="true"/>
<f:selectItems value="#{homeController.descriptions}" var="desc"
itemValue="#{desc}" itemLabel="#{desc}"/>
</p:selectOneMenu>
</f:facet>
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{msg.description}"/></f:facet>
<f:facet name="input"> <p:inputText id="desc-input" value="#{msg.description}"
style="width:85%"/></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="جزئیات" style="width:40px">
<p:commandLink action="#{homeController.setMessageToShow(msg)}" ajax="true"
update="img-dlg-box" oncomplete="PF('imgDlgBox').show()">
<i class="fa fa-blue fa-desktop"/>
</p:commandLink>
</p:column>
<p:column headerText="مشاهده گفتگو" style="width:40px">
<p:commandLink action="#{homeController.showConversation(msg.sender, msg.receiver)}"
ajax="true" update="conv-dlg-box" oncomplete="PF('convDlgBox').show()">
<i class="fa fa-blue fa-wechat"/>
</p:commandLink>
</p:column>
</p:dataTable>
</h:form>
My "search" button:
<p:commandButton value="جست‌وجو" action="#{homeController.search}" update=":contents-form:tbl msgs"
icon="fa fa-search"/>
My "display" button:
<p:commandButton value="نمایش" icon="fa fa-desktop" action="#{homeController.loadArchive}"
update="contents-form msgs"/>
search method in the backing bean:
public void search() {
if (this.selectedArchive == null) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "خطا!", "لطفا یک مجموعه را انتخاب کنید"));
return;
}
if ((this.textQuery != null && !this.textQuery.equals(""))
|| (this.selectedNodes != null && this.selectedNodes.length > 0)) {
logger.info(String.format("searching '%s' in archive %d ...", this.textQuery, this.selectedArchive.getId()));
List<String> selectedWords = this.getSelectedWords(this.selectedNodes);
searchText(this.textQuery, selectedWords);
} else {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "خطا!", "برای جست‌وجو هیچ متنی وارد نشده و هیچ واژه‌ای انتخاب نشده است."));
return;
}
extractChoices();
// Disable default sorting:
DataTable table = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent(":contents-form:tbl");
table.setValueExpression("sortBy", null);
table.setValueExpression("sortOrder", null);
}
And loadArchive method in the backing bean:
public void loadArchive() {
if (this.selectedArchive == null) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "خطا!", "لطفا یک مجموعه را انتخاب کنید"));
return;
}
this.messagesModel = new LazyMessageModel(this.selectedArchive, true, this.messageService);
extractChoices();
// Enable default sorting:
FacesContext context = FacesContext.getCurrentInstance();
ExpressionFactory ef = context.getApplication().getExpressionFactory();
DataTable table = (DataTable) context.getViewRoot().findComponent(":contents-form:tbl");
ValueExpression sortVe = ef.createValueExpression(context.getELContext(), "#{msg.date}", Message.class);
table.setValueExpression("sortBy", sortVe);
table.setSortOrder("descending");
logger.info(String.format("archive %d loaded", (this.selectedArchive.getId())));
}
Spec:
Primefaces 6.2
JSF 2.2.14
Java 1.8

I finally found a clean solution! Just I must reset the table in addition to setting sortBy null after clicking "search" button:
public void search() {
// Do something ...
DataTable table = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent(":contents-form:tbl");
table.reset();
table.setValueExpression("sortBy", null);
}

Related

Primefaces dataTable columns sequence by displayPriority parameter

I try to change Primefaces dataTable columns sequence using displayPriority parameter. But it does not work.If I try to change isVisible parameter or Width parameter of column everything works fine, but displayPriority does not work, why?
My xhtml:
<p:dataTable id="dataTableIncomingDoc"
var="item"
scrollable="true"
scrollHeight="100%"
scrollWidth="100%"
showGridlines="true"
selectionMode="single"
draggableColumns="true"
resizableColumns="true"
size="small"
styleClass="fixed-size"
selection="#{docsBean.docEntitySelected}"
rowKey="#{item.id}"
value="#{docsBean.loadDocsList()}">
<p:column id="registrationDate"
headerText="Reg. date"
width="100"
filterBy="#{item.registrationDate}"
sortBy="#{item.registrationDate}"
filterMatchMode="contains">
<h:outputText value="#{item.registrationDate}"/>
</p:column>
<p:column id="regNr"
headerText="Reg. Nr."
width="100"
filterMatchMode="contains"
sortBy="#{item.regNr}"
filterBy="#{item.regNr}">
<h:outputText value="#{item.regNr}"/>
</p:column>
<p:column id="documentNr"
headerText="Doc. Nr."
width="100"
filterMatchMode="contains"
sortBy="#{item.docNr}"
filterBy="#{item.docNr}">
<h:outputText value="#{item.docNr}"/>
</p:column>
</p:dataTable>
My bean:
public List<DocEntity> loadDocsList() {
var dataTable = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent("mainForm:dataTableIncomingDoc");
var a = dataTable.getColumns().get(1);
var b = dataTable.getColumns().get(2);
((Column) a).setDisplayPriority(2);
((Column) b).setDisplayPriority(1);
PrimeFaces.current().ajax().update(dataTable);
return docsList;
}

In Cell editing does not update value on focus change

Cell value is not captured when mouse focus changes
I have a simple datatable that shows the name and income. The cell values are editable. When I update the cell value with a different value and hit "Update" (basically change mouse focus) the new value is not captured. The update method
prints the old value. However, when I press the "tab" key I can see the updated values printed. I am not sure what I am missing
Here is my backing bean:
#PostConstruct
public void init() {
NVPair nvp = new NVPair("xx", 10000);
dataList.add(nvp);
nvp = new NVPair("yy", 20000);
dataList.add(nvp);
}
public void update() {
for (NVPair item : dataList) {
System.out.println("Name: " + item.getName() + " Value: " +
item.getValue());
}
}
Here is the view:
<h:form>
<p:dataTable id="testTable" value="#{testBean.dataList}" var="item"
editable="true" editMode="cell">
<p:ajax event="cellEdit" listener="#{testBean.onCellEdit}"
immediate="true" update="testTable" />
<p:column headerText="Name">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{item.name}" />
</f:facet>
<f:facet name="input">
<h:outputText value="#{item.name}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Income">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{item.value}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{item.value}" />
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
<p:commandButton action="#{testBean.update}" value="Update" />
</h:form>
When the focus changes, I am expecting that the edited value is captured just like when the tab key is pressed.

My form does not get some object push values for Controller

When I need to look up the object that my controller finds in the base and return the object, but in my form does not show, only some fields.
When the field is disabled true the value is show but if disabled is false is not show !!
My form
<h:form id="frm" prependId="false">
<p:panelGrid columns="2" layout="grid"
styleClass="panelgrid-noborder"
style="margin-top: 10px;"
columnClasses="ui-grid-col-1, ui-grid-col-2">
<p:outputLabel value="Id" for="id"/>
<p:inputText id="id"
value="#{planoController.plano.id}"
disabled="true">
<p:ajax event="blur" update="frm" listener="#{planoController.findById()}"/>
</p:inputText>
</p:panelGrid>
<p:panelGrid columns="2" layout="grid"
styleClass="panelgrid-noborder"
style="margin-top: 10px;"
columnClasses="ui-grid-col-1, ui-grid-col-6">
<p:outputLabel value="Nome" for="nome"/>
<p:inputText id="nome"
value="#{planoController.plano.nome}"/>
</p:panelGrid>
<p:dataTable id="tblPlanos"
value="#{planoController.planos}"
var="plano"
rows="20"
paginator="true"
paginatorPosition="bottom"
reflow="true"
emptyMessage="Nenhum Plano Cadastrado">
<p:column headerText="#" width="5%">
<p:commandButton icon="ui-icon-pencil" update="frm" immediate="true">
<f:setPropertyActionListener value="#{plano}" target="#{planoController.planoSelecionado}" />
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
My Controller
public void setPlanoSelecionado(Plano planoSelecionado) {
this.planoSelecionado = planoSelecionado;
findPlanoSelecionado();
}
/**
* Retorna Plano Selecionado
* */
public void findPlanoSelecionado(){
plano = this.planoService.findById(planoSelecionado.getId());
}

rowToggle should call first rowSelect event jsf primefaces

<p:dataTable var="item" id="datatable-list" value="#{generalJournalEntryMB.generalJournalEntries}" rows="10"
paginator="true" reflow="true" paginatorPosition="top" rowExpandMode="single"
rendered="#{generalJournalEntryMB.generalJournalEntries.size() > 0}" rowIndexVar="rowIndex"
paginatorTemplate="{CurrentPageReport} {PreviousPageLink} {NextPageLink} " rowKey="#{item.id}"
selectionMode="single" selection="#{generalJournalEntryMB.generalJournalEntry}" widgetVar="datatable-list">
<p:column style="width:16px">
<p:rowToggler />
</p:column>
<p:column headerText="Id">
<h:outputText value="#{item.id}" />
</p:column>
<p:column headerText="Description">
<h:outputText value="#{item.description}" />
</p:column>
<p:column headerText="Amount">
<h:outputText value="#{item.amount}" />
</p:column>
<p:column headerText="Reference">
<h:outputText value="#{item.reference}" />
</p:column>
<p:column headerText="State">
<h:outputText value="#{item.postingState.value}" />
</p:column>
<p:rowExpansion id="expand" rendered="true">
<p:panelGrid columns="2" columnClasses="label,value" style="width:300px">
<h:outputText value="Id:" />
<h:outputText value="1" />
<h:outputText value="Year" />
<h:outputText value="1983" />
<h:outputText value="Color:" />
<h:outputText value="White" />
<h:outputText value="Price" />
<h:outputText value="#{generalJournalEntryMB.price}" />
</p:panelGrid>
</p:rowExpansion>
<p:ajax event="rowSelect" listener="#{generalJournalEntryMB.rowSelectListener}" update="main:top-menu-bar" />
<p:ajax event="rowToggle" listener="#{generalJournalEntryMB.rowToggleListener}" update="main:top-menu-bar" />
</p:dataTable>
When I expand the row without selecting the row, it show nothing. Currently what am I doing is to first select row and expand it to get desire result.
How we can trigger rowSelect even / ajax call automatically when rowToggle event fire?
You can override primefaces toggleExpansion function so it executes selectRow before
PrimeFaces.widget.DataTable.prototype.toggleExpansion = (function() {
var cached_function = PrimeFaces.widget.DataTable.prototype.toggleExpansion;
return function() {
var row = arguments[0].closest('tr');
if(this.cfg.selectionMode === 'single') {
this.unselectAllRows();
}
if(this.cfg.selectionMode){
this.selectRow(row, false);
}
var result = cached_function.apply(this, arguments);
return result;
};
})();

Primefaces datatable not editing

I'm trying to make editable primefaces datatable. I'm using http://www.primefaces.org/showcase/ui/datatableRowEditing.jsf. All database table data showing up, but then I trying to edit data in a table I'm getting following error:
/index.xhtml #23,90 listener="#{tableBean.onEdit}": Target Unreachable, identifier 'tableBean' resolved to null: javax.el.PropertyNotFoundException: /index.xhtml #23,90 listener="#{tableBean.onEdit}": Target Unreachable, identifier 'tableBean' resolved to null
index.xhtml
<h:head>
<title>index.xhtml</title>
</h:head>
<h:body>
<h:form id="form">
<p:growl id="messages" showDetail="true"/>
<p:dataTable var="u" value="#{logonTest.userList}" id="carList" editable="true">
<f:facet name="header">
In-Cell Editing
</f:facet>
<p:ajax event="rowEdit" listener="#{tableBean.onEdit}" update=":form:messages" />
<p:ajax event="rowEditCancel" listener="#{tableBean.onCancel}" update=":form:messages" />
<p:column headerText="Name" style="width:30%">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{u.name}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{u.name}" style="width:100%"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Surname" style="width:20%">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{u.surname}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{u.surname}" style="width:100%" />
</f:facet>
</p:cellEditor>
</p:column>
TableBean.java
public void onEdit(RowEditEvent event) {
FacesMessage msg = new FacesMessage(" Edited", ((User) event.getObject()).getName());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onCancel(RowEditEvent event) {
FacesMessage msg = new FacesMessage(" Cancelled", ((User) event.getObject()).getName());
FacesContext.getCurrentInstance().addMessage(null, msg);
}