Primefaces Tree Navigation - jsf-2

As a follow-up to the question I had asked before, now that primefaces 5.2 is available, I cannot seem to get the tree to be navigated using arrow keys. As I mentioned before, in the showcase, one can use the arrow-keys to navigate, expand or collapse nodes. Using exactly the same code locally does not however allow this arrow-keys navigation.
Is there a specific attribute i need to add to the tree element?
How does one enable arrow-keys navigation, expand and context?
here is the tree snippet:
<p:tree value="#{treeEventsView.root}" var="doc" selectionMode="single" selection="#{treeEventsView.selectedNode}" dynamic="true">
<p:ajax event="expand" update=":form:messages" listener="#{treeEventsView.onNodeExpand}" />
<p:ajax event="collapse" listener="#{treeEventsView.onNodeCollapse}" />
<p:ajax event="select" listener="#{treeEventsView.onNodeSelect}" />
<p:ajax event="unselect" listener="#{treeEventsView.onNodeUnselect}" />
<p:treeNode expandedIcon="ui-icon-folder-open" collapsedIcon="ui-icon-folder-collapsed" ariaLabel="Folder" >
<h:outputText value="#{doc.name}"/>
</p:treeNode>
<p:treeNode type="document" icon="ui-icon-document">
<h:outputText value="#{doc.name}" />
</p:treeNode>
<p:treeNode type="picture" icon="ui-icon-image">
<h:outputText value="#{doc.name}" />
</p:treeNode>
<p:treeNode type="mp3" icon="ui-icon-video">
<h:outputText value="#{doc.name}" />
</p:treeNode>
</p:tree>

Related

Datatable cellEditor functionality in forEach generated Datatable

I am trying to generate a editable datatable dynamically dependend on the resultset of an previously executed SQL-Query.
Depending on which columns would have a constant value I am trying to not render them. That part of the code works just fine, everything is displayed as i would like it to be.
My issues are with the cellEditor. I generate my datable as follows:
<p:dataTable ajax="true" var="mBT" value="#{stammdaten.bbvList}" id="meldeBearbeitungsTable" editable="true" editMode="cell" scrollable="true" scrollHeight="400" style="width:600px">
<p:ajax event="cellEdit" listener="#{stammdaten.onCellEdit}" update=":Mb:message"/>
<c:forEach var="column" items="#{stammdaten.columns}">
<p:column headerText="#{column.header}">
<f:attribute name="myCol" value="#{column}" />
<span>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{mBT[column.property]}"></h:outputText>
</f:facet>
<f:facet name="input">
<p:inputText value="#{mBT[column.property]}">
<p:keyFilter regEx="/[0-9]/i"/>
</p:inputText>
</f:facet>
</p:cellEditor>
</span>
</p:column>
</c:forEach>
</p:dataTable>
bbvList is a List of beans with different values.
columns is a List of beans to identify the header-Texts coresponding to the respective variables.
So now the issue itself:
This is how the cellEditor looks like when i click on it:
Issue-Picture
So in that example i tried to edit the field with the value "8" in it. onCellEdit gets triggered (a System.out.println is getting printed on the console) but i cant actually change the value in the respective field.
Does have cellEdit issues with the forEach initialisition of the dataTable? If yes is there a way to fix it? Else what am i doing wrong?
Since only a specific component of the html-side of code isnt working as it should be i won't post unnecessary java-Code for now. If needed i will add that as well.
Hope someone can help :)
Turns out the attribute and/or span where the cause of the problem. Simply removing them solved the issue with the cellEdit.
following works fine :
<p:dataTable ajax="true" var="mBT" value="#{stammdaten.bbvList}" id="meldeBearbeitungsTable" editable="true" editMode="cell" scrollable="true" scrollHeight="400" style="width:600px">
<p:ajax event="cellEdit" listener="#{stammdaten.onCellEdit}" update=":Mb:message"/>
<c:forEach var="column" items="#{stammdaten.columns}">
<p:column headerText="#{column.header}">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{mBT[column.property]}"></h:outputText>
</f:facet>
<f:facet name="input">
<p:inputText value="#{mBT[column.property]}">
<p:keyFilter regEx="/[0-9]/i"/>
</p:inputText>
</f:facet>
</p:cellEditor>
</p:column>
</c:forEach>
</p:dataTable>

Primefaces data for data table is getting confused

Sorry for the title but I have to explain what I want to do and what isn't working. My web ui with JSF 2.2.10 and primefaces 5.2.6 shows a search mask and search results upon a model.
Each search instance is shown as a tab in a tabView. When a tab is clicked, its corresponding search instance is shown under the tabView in a dataTable. A search instance is created upon a search template, so different search instances can have different input fields and different result fields (which are the columns in the data table).
The user is able to execute the search for an existing search instance again with or without changed search fields. Here is my problem...he ui work until the user has executed a search instance 2nd time. Now when the tab in the tabView is changed an exception is thrown and the javascript console shows 'Request return with error:parsererror primefaces.js.jsf?ln=primefaces$v=5.2.6:1'
Now the data of for instance search instance 1 is mixed up with search instance 2. A result field (data table column) from search instance 1 is tried to get from search instance 2, but this can fail.
This only occurs if a search instance is executed the 2nd time. Without 2nd execution I can change between the tabs without problem. My data structure is ok I think.
A class SearchInstance is "behind" a tab and contains a list of SearchResult. This SearchResult is a Map with the result fields.
This is the xhtml of the tabView. The tabView is only used as trigger here. A tab does not really contain the dataTable with the components, it updates only the form and the content is included under the tabView:
<h:form id="searchInstancesFormId">
<p:tabView id="searchTabViewId" value="#{searchBL.searchInstances}" var="curSearch" activeIndex="#{searchBL.activeTabIndex}">
<p:ajax event="tabChange" oncomplete="resizeResultViews();" listener="#{searchBL.setSelectedSearch(curSearch)}"
update="#form" immediate="true" process="#this" />
<p:ajax event="tabClose" listener="#{searchBL.removeSearchInstance(curSearch)}" update="#this"
oncomplete="resizeResultViews();" immediate="true" process="#this" />
<p:tab closable="#{curSearch.isCloseable()}">
</p:tab>
</p:tabView>
<h:panelGrid id="mainSearchAreaGridId">
<ui:include
src="#{not searchBL.selectedSearch.closeable ? '/sections/search/firstSearchTab.xhtml' : '/sections/search/searchInstanceTab.xhtml'}">
<ui:param name="curSearchInst" value="#{searchBL.selectedSearch}" />
</ui:include>
</h:panelGrid>
</h:form>
The 1st tab is the search template tab from the 2nd tab on there are search instances.
Here is the dataTable xhtml. The problem occurs when curValue is retrieved. Here in 'hitlistBL' bean the result field map is queried with the current property name. Here the name from the search instance selected before and it is tried to get the value from the new selected search instance:
<p:dataTable id="searchResultTableId" scrollable="true" value="#{curSearch.getSearchResults()}" scrollHeight="300" var="curSearchResult"
sortMode="multiple" rowKey="#{curSearchResult.hashCode()}" draggableColumns="true" resizableColumns="true" styleClass="hitlistDataTable"
paginator="true" rows="#{curSearch.hitlistRowsPerPage}" rowIndexVar="rowIndex" filteredValue="#{curSearch.filteredValues}"
selection="#{curSearch.selectedSearchResults}" widgetVar="hitlistTableVar">
<p:ajax event="rowSelect" update="#(.resultlistActionGrid) :searchInstancesFormId:listResultTabViewId:searchResultTableContextMenuId" />
<p:ajax event="rowUnselect" update="#(.resultlistActionGrid) :searchInstancesFormId:listResultTabViewId:searchResultTableContextMenuId" />
<p:ajax event="toggleSelect" update="#(.resultlistActionGrid) :searchInstancesFormId:listResultTabViewId:searchResultTableContextMenuId" />
<p:ajax event="rowSelectCheckbox"
update="#(.resultlistActionGrid) :searchInstancesFormId:listResultTabViewId:searchResultTableContextMenuId" />
<p:ajax event="rowUnselectCheckbox"
update="#(.resultlistActionGrid) :searchInstancesFormId:listResultTabViewId:searchResultTableContextMenuId" />
<p:ajax event="contextMenu" update="#(.resultlistActionGrid) :searchInstancesFormId:listResultTabViewId:searchResultTableContextMenuId"
oncomplete="PF('searchResultTableContextMenuVar').show(currentEvent);" />
<!-- double click listener -->
<p:ajax event="rowDblselect"
listener="#{editPropertyBL.initForEdit(curSearch.selectedSearchResults.get(0), curSearch.getDataViewDefinition())}"
oncomplete="PF('editPropertyDialogVar').show();" update=":editPropertyFormId #(.resultlistActionGrid)" />
<p:column style="width: 16px;">
<p:rowToggler />
</p:column>
<p:column selectionMode="multiple" style="width: 16px; text-align:center; padding-right: 12px;" />
<p:columns value="#{curSearch.determinePrimaryPropertyNames()}" var="curPrimaryPropName"
sortBy="#{curSearchResult[curPrimaryPropName].getValue()}" filterBy="#{curSearchResult[curPrimaryPropName].getValue()}"
filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="#{displayNameResolver.resolveDisplayNameOfHitlistProperty(curPrimaryPropName, curSearch)}" />
</f:facet>
<ui:param name="curValue" value="#{hitlistBL.generatePropertyValue(curSearchResult, curPrimaryPropName)}" />
<ui:param name="isDocumentTitle" value="#{hitlistBL.isDocumentTitle(curPrimaryPropName)}" />
<ui:param name="isChoice" value="#{hitlistBL.isChoice(curPrimaryPropName, curSearch)}" />
<!-- doc title -->
<h:panelGroup rendered="#{curSearchResult.isChanged() and (isDocumentTitle)}" style="padding-right: 4px;">
<i class="fa fa-refresh" />
</h:panelGroup>
<!-- <p:commandLink action="#{contentBL.showContentExtern(curSearch.getViewId(), curSearchResult)}" value="#{curValue}" ajax="false"
rendered="#{(curSearchResult.isOfDataType('STRING', curPrimaryPropName)) and (isDocumentTitle) and (not isChoice)}" target="_blank" /> -->
<!-- document title -->
<h:outputText value="#{curValue}" title="#{curSearchResult.getRepresentationsAsString()}"
rendered="#{(curSearchResult.isOfDataType('STRING', curPrimaryPropName)) and (isDocumentTitle) and (not isChoice)}" />
<!-- data type STRING -->
<h:outputText value="#{curValue}"
rendered="#{curSearchResult.isOfDataType('STRING', curPrimaryPropName) and (not isDocumentTitle) and (not isChoice)}" />
<!-- data type UUID -->
<h:outputText value="#{curValue}" rendered="#{curSearchResult.isOfDataType('UUID', curPrimaryPropName) and (not isChoice)}" />
<!-- data type INTEGER32 -->
<h:outputText value="#{curValue}" rendered="#{curSearchResult.isOfDataType('INTEGER32', curPrimaryPropName) and (not isChoice)}">
<f:convertNumber integerOnly="true" groupingUsed="false" />
</h:outputText>
<!-- data type DOUBLE -->
<h:outputText value="#{curValue}" rendered="#{curSearchResult.isOfDataType('DOUBLE', curPrimaryPropName) and (not isChoice)}">
<f:convertNumber groupingUsed="false" />
</h:outputText>
<!-- data type DATETIME -->
<h:outputText value="#{curValue}" rendered="#{curSearchResult.isOfDataType('DATETIME', curPrimaryPropName) and (not isChoice)}">
<f:convertDateTime type="both" dateStyle="short" timeStyle="short" timeZone="#{settingsBL.getTimeZoneIdSet()}"
pattern="#{settingsBL.dateTimePattern}" />
</h:outputText>
<!-- CHOICE -->
<h:outputText value="#{hitlistBL.determineChoiceUiValue(curSearch.getViewId(), curSearchResult, curPrimaryPropName)}"
rendered="#{(not isDocumentTitle) and (isChoice)}" />
</p:columns>
</p:dataTable>
A search instance if executed with the following. A new search is done and the search instance member search result is exchanged with the new results:
<p:commandButton id="doSearchButtonFullMaskId" value="#{msgs['label.button.searchTemplate.search']}" icon="searchButtonIcon"
styleClass="searchButton" action="#{searchMaskBL.doSearch(curSearchInst)}" update="#form" process="#form"
oncomplete="resizeResultViews(); PF('hitlistTableVar').clearFilters();" style="margin-top: 10px;" />
Sorry this is a lot of text and it is quite difficult to explain. I don't know if this is my flaw or there is a bug somewhere. Maybe this javascript parsererror could give a hint, but I do not know how to get into/debug it.
Update: looks like a not wellformed xml of the ajax response?:
XML-Verarbeitungsfehler: nicht wohlgeformt Adresse: moz-nullprincipal: {96f3db57-4075-4d80-a250-03491a2ce33f} Zeile Nr. 90, Spalte 132: ...rrorpages/500.xhtml?dswid=-9189"></redirect>]]>]]></update></partial-response......-------------------------------------------------^
It points to the closing brackets of ></redirect>]]>]]><

Primefaces data table Row selection and multiple checkbox selection not working

I am using primeface 3.5 where i find the check box to select and unselect or row select work perfectly independently . While I tried to have both the row selection and check box selection ,row selection event is not triggering . Could any one clarify this for me ?
row select is not working thou check all event is working
<p:dataTable id="myBookDTable" var="car" value="#{myBean.pageViews}" paginatorPosition="bottom" paginator="true" rows="30" scrollable="true" scrollHeight="400" scrollRows="30" paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}" rowsPerPageTemplate="30,50,100"rowKey="#{car.carID}" rowIndexVar="rowIndex" draggableColumns="true" lazy="true">
<p:ajax event="rowSelect" listener="#{myBean.onRowSelect}" update="certainpart"
async="true"/>
<p:ajax event="rowSelectCheckbox" listener="#{myBean.rowSelectCheckbox}"/>
<p:ajax event="rowUnselectCheckbox" listener="#{myBean.rowUnselectCheckbox}"/>
<p:ajax event="rowUnselect" listener="#{myBean.rowUnselect}"/>
<p:column width="30" selectionMode="multiple" style="width:2%" />
</p:datatable>
For column header event we have a different header name exist in primeface/jsf:
"toggleSelect".
You can use like this:
<p:ajax event="toggleSelect" update="#this" process="#this" />
In your datatable tag,
Use this
<p:ajax event="rowSelectCheckbox" update="someComponent" />
<p:ajax event="rowUnselectCheckbox" update="someComponent" />
<p:ajax event="rowSelect" update="someComponent" />
<p:ajax event="rowUnselect" update="someCompoent" />
<p:column selectionMode="multiple" style="width:4%" />
you need to fire these four ajax events and make sure you make the column selectionMode as multiple
Try this:
<p:ajax event="toggleSelect" update=":form:component" partialSubmit="true" />
The source:
PrimeFaces 4.0 User Guide.- Ajax Behavior Events

Primefaces dataTable rowIndexVar with pagination

I'm using a primefaces datatable with single row selection and pagination. For each row I have some commandlinks (one of which is disabled) that I want the user to click to perform operations on that row (example: delete, edit).
In order to provide visual confirmation that the user clicked the button on the right row, I want the row to be selected upon clicking and then proceed to the desired bean method.
This is working as intended if the table has only one page or if it's page 1; on all other pages I get a NullPointerException.
I figured out why this happens: I use rowIndexVar to perform the selection but it seems to be returning the index related to the whole table and the selectRow method expects an index related to the current page. Meaning that if I have 10 rows per page and I click on the third row in the second page, the index returned is "12" and not "2" and selectRow(12, false) returns null as there are only 10 items on that page.
My question is: how can I pass the correct rowIndex so I get the correct selection on all pages?
The backing bean is ViewScoped and the methods aren't nothing extraordinary but since it has a lot of code related to webservices and jaxb generated classes and I signed an NDA I can't paste it here (I'm already pushing it by sharing the datatable code).
<p:dataTable id="dataTable" var="item" rowIndexVar="rowIndex"
value="#{dgRefTypePubBean.itemList}"
widgetVar="itemsTable"
filteredValue="#{dgRefTypePubBean.filteredItems}" paginator="true"
rows="10"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="2,5,10,20" rowKey="#{item.EID}"
selection="#{dgRefTypePubBean.selectedItem}" selectionMode="single"
emptyMessage="#{msgs['dgreftype.datatable.message.emptyList']}"
resizableColumns="false">
<p:ajax event="page" oncomplete="itemsTable.unselectAllRows(); itemsTable.selectRow(0, false)" />
<p:ajax event="rowSelect" listener="#{dgRefTypePubBean.onRowSelect}"
update=":form:obs :form:index_info :form:elimination_just :form:left_footer :form:right_footer" />
<p:ajax event="rowUnselect" listener="#{dgRefTypePubBean.onRowUnselect}" update=":form:obs" />
<p:column style="text-align:right; width:22px; border:none; background:white">
<h:graphicImage rendered="#{item.EState==2}" library="images" name="data-delete.png" width="15" height="15" style="border:none; padding:0" />
</p:column>
<p:column id="codColumn" headerText="#{msgs['dgreftype.datatable.label.functionalCode']}" filterStyle="height:10px; font-weight:normal" style="text-align:left; width:120px" filterBy="#{item.EFunctionalCode}">
<h:outputText value="#{item.EFunctionalCode}" />
</p:column>
<p:column id="designationColumn" headerText="#{msgs['dgreftype.datatable.label.name']}" filterStyle="height:10px; font-weight:normal" style="text-align:left; word-wrap: break-word" filterBy="#{item.EName}">
<h:outputText value="#{item.EName}" />
</p:column>
<p:column id="variableColumn" headerText="#{msgs['dgreftype.datatable.label.variableTypeName']}" filterStyle="height:10px; font-weight:normal" style="text-align:left; width:200px" filterBy="#{item.EVariableTypeName}">
<h:outputText value="#{item.EVariableTypeName}" />
</p:column>
<p:column id="buttonsColumn" style="width:55px">
<h:panelGrid columns="3" style="border-collapse:separate; border:none !important">
<h:commandLink onclick="itemsTable.unselectAllRows(); itemsTable.selectRow(#{rowIndex}, false)" action="#{dgRefTypePubBean.editSelectedItem()}">
<h:graphicImage library="images" name="edit-text.png" width="15" height="15" style="border:none" />
</h:commandLink>
<h:graphicImage library="images" name="detail-disabled.png" width="15" height="15" style="border:none" onclick="itemsTable.unselectAllRows(); itemsTable.selectRow(#{rowIndex}, false)" />
<h:commandLink onclick="itemsTable.unselectAllRows(); itemsTable.selectRow(#{rowIndex}, false); confirmation.show(); return false;">
<h:graphicImage library="images" name="edit-delete.png" width="15" height="15" style="border:none" />
</h:commandLink>
</h:panelGrid>
</p:column>
</p:dataTable>
I'm using JSF 2.0 and Primefaces 3.4.2.
Thanks in advance
It is possible to get the current page from the paginator with this function :
itemsTable.paginator.getCurrentPage()
So, we can calculate the correct row index from this value, the value of #{rowIndex} and the maximum number of row per page.
<h:commandLink onclick="itemsTable.unselectAllRows(); itemsTable.selectRow(#{rowIndex}-itemsTable.paginator.getCurrentPage()*10)" action="#{dgRefTypePubBean.editSelectedItem()}">
<h:graphicImage library="images" name="edit-text.png" width="15" height="15" style="border:none" />
</h:commandLink>
I hope this help.
Regards.

p:dataTable not updating after deleting row

I have searched this topic and tried all the suggestions, however I just cannot seem to get what seems to be a very simple thing to work.
I have a PrimeFaces 3.4 <p:dataTable> with data populated from a List in my backing bean and with a <p:commandLink> in one of the columns for every row. I am just trying to implement a simple delete and refresh of the data table. However although the element is removed from the List object, the data table does not refresh.
Bean (view scoped):
public void deleteRow(rowType row){
this.tableDataList.remove(row);
}
View:
<h:form id="form">
<p:dataTable id="dt" var="dt" value=#{managedBean.tableDataList}
rowKey="#{dt.id}" selection="#{managedBean.selectedRow}"
selectionMode="single">
<p:column><h:outputText value="#{dt.field1}"/></p:column>
<p:column><h:outputText value="#{dt.field2}"/></p:column>
<p:column><h:outputText value="#{dt.field3}"/></p:column>
<p:column width="60">
<p:commandLink id="deleteCl"
value="Delete"
actionListener="#{managedBean.deleteRow(dt)}"
update=":form:dt"
/>
</p:column>
</h:form>
From what I can see, a data table in PrimeFaces 3.4 should be able to be updated via a child component such as a command link, but I just can't get it to work. I have a phase listener implemented so I can see that there are no validation or other errors before the render response phase, but the data table continues to display the deleted row unless I refresh the browser window, then it will disappear.
It works if I set ajax="false" in the command link, but then the entire page is updated unnecessarily.
I have tried:
Changing between action and actionListener
Making the following changes in various combinations to the command link attributes:
process="#this"
update="#this"
update="#form"
The annoying thing is that I have a similar table with a command link where each link opens up a dialog window containing another data table that is populated with data retrieved based upon the row that was initially clicked. Works perfectly on the same page. Agh!
Try modeling some points from this to see if it helps you.
<h:outputText escape="false" value="#{message.noCompaniesFound}" rendered="#{companyController.companyModel.rowCount == 0}"/>
<h:panelGroup rendered="#{companyController.companyModel.rowCount > 0}">
<p:commandButton id="addButton" value="#{message.newCompany}" oncomplete="companyDialog.show()" icon="ui-icon-plus" title="#{message.addCompany}" rendered="#{loginController.privileges.contains(bundle.SuperUser)}"/>
<p:dataTable id="companyList" var="company" widgetVar="companyTable" value="#{companyController.companyModel}" rowKey="#{company.name}" selection="#{companyController.selectedCompany}" selectionMode="single"
paginator="true" rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15,20,50,100">
<p:ajax event="rowEdit" update="#this" listener="#{companyController.saveCompany(company)}">
<f:param name="company" value="#{company}"/>
</p:ajax>
<f:facet name="header">
<p:outputPanel>
<h:outputText value="#{message.search}: "/>
<p:inputText id="globalFilter" onkeyup="companyTable.filter()"/>
</p:outputPanel>
</f:facet>
<p:column id="name" headerText="#{message.name}" filterBy="#{company.name}" filterMatchMode="contains" filterStyle="display: none;">
<h:outputText value="#{company.name}"/>
</p:column>
<p:column headerText="#{message.editOptions}" style="width:10px;">
<p:commandButton id="editButton" update=":companyForm" oncomplete="editDialog.show()" icon="ui-icon-pencil" title="#{message.edit}">
<f:setPropertyActionListener value="#{company}" target="#{companyController.selectedCompany}"/>
</p:commandButton>
<p:commandButton id="deleteButton" update=":companyForm" oncomplete="confirmation.show()" icon="ui-icon-trash" title="#{message.delete}">
<f:setPropertyActionListener value="#{company}" target="#{companyController.selectedCompany}"/>
</p:commandButton>
</p:column>
<f:facet name="footer">
</f:facet>
</p:dataTable>
</h:panelGroup>
<p:confirmDialog id="confirmDialog" message="#{message.sureYouWantToDelete} #{companyController.selectedCompany.name} ?" severity="alert" widgetVar="confirmation">
<p:commandButton id="confirm" value="#{message.yes}" onclick="confirmation.hide()" actionListener="#{companyController.deleteCompany}" update="companyForm" />
<p:commandButton id="decline" value="#{message.no}" onclick="confirmation.hide()"/>
</p:confirmDialog>

Resources