środa, 5 października 2016

Primefaces Datatable with editable rows, add button and remove button

So the goal is to implement something like that:







So as you can see we have editable component. It is possible to add new row. When the row is being edited Apply button is disabled and also when you add new row the row is automatically set to edit mode.
Let's take a look at the implementation:
This is an implementation of a from containing datable:

<h:form id="restCallStepEditionForm">
.
.
.
.
<p:tab id="queryParamTab" title="Query Parameters">
....
</p:tab>
<p:tab id="queryParamTab" title="Query Parameters">
<job:restServiceParamTable id="queryParamTableId" managedBean="#{restCallStepBean}" panelId="queryParamTablePanel" addParamCommandButtonId="addQueryParam"
dataTableValue="#{restCallStepBean.queryParams}" cellWidgetVar="cellQueryParams"
panelToUpdate="jobPlanEditionComp:restCallStepEditionComp:restCallStepEditionForm:paramsTab:queryParamTableId:queryParamTablePanel"/>
</p:tab>
<p:tab id="postParamTab" title="Post Parameters">
....
</p:tab>
</p:tabView>
<f:facet name="footer">
<p:outputPanel layout="block" style="text-align: right">
<p:commandButton id="applyButton" value="Apply" update="@form #{cc.attrs.update}"
actionListener="#{restCallStepBean.onApplyStepEdition}" validateClient="true"
oncomplete="onApplyStepComplete(xhr,status,args);"
disabled="#{restCallStepBean.getParamBeingEditable()}"
icon="ui-icon ui-icon-check"/>
<p:commandButton id="closeButton" value="Close" onclick="PF('restCallStepEditionDialog_widget').hide();"
type="button" icon="ui-icon ui-icon-close" immediate="true" process="@this"/>
</p:outputPanel>
</f:facet>
</p:panelGrid>
</h:form>
view raw gistfile1.txt hosted with ❤ by GitHub
As you can see we used jsf compositions here. Take a look at the implementation of datatable:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:job="http://java.sun.com/jsf/composite/app/job"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:rd="http://java.sun.com/jsf/composite/rapiddeploy-faces"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="managedBean" />
<composite:attribute name="panelId" />
<composite:attribute name="addParamCommandButtonId" />
<composite:attribute name="dataTableValue" />
<composite:attribute name="panelToUpdate" />
<composite:attribute name="cellWidgetVar" />
</composite:interface>
<composite:implementation>
<p:panel id="#{cc.attrs.panelId}">
<p:commandButton id="#{cc.attrs.addParamCommandButtonId}"
process="@this" immediate="true" update="#{cc.attrs.panelId} jobPlanEditionComp:restCallStepEditionComp:restCallStepEditionForm:applyButton"
icon="ui-icon ui-icon-plus" styleClass="ui-panel-titlebar-icon ui-corner-all ui-state-default"
actionListener="#{cc.attrs.managedBean.onNewParam(cc.attrs.panelId)}"
oncomplete="$('.ui-datatable-data tr').find('span.ui-icon-pencil').last().each(function(){this.click()})" >
</p:commandButton>
<p:dataTable value="#{cc.attrs.dataTableValue}" var="entry" editable="true" widgetVar="#{cc.attrs.cellWidgetVar}"
scrollRows="6" scrollHeight="100" scrollable="true" resizableColumns="true" >
<p:ajax event="rowEdit" listener="#{cc.attrs.managedBean.onRowEdit}" update="jobPlanEditionComp:restCallStepEditionComp:restCallStepEditionForm:applyButton" />
<p:ajax event="rowEditInit" listener="#{cc.attrs.managedBean.onRowEditInit}" update="jobPlanEditionComp:restCallStepEditionComp:restCallStepEditionForm:applyButton"/>
<p:ajax event="rowEditCancel" listener="#{cc.attrs.managedBean.onRowEditCancel}" update="jobPlanEditionComp:restCallStepEditionComp:restCallStepEditionForm:applyButton"/>
<p:column>
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{entry.key}" /></f:facet>
<f:facet name="input"><p:inputText value="#{entry.key}" style="width:96%"/></f:facet>
</p:cellEditor>
</p:column>
<p:column>
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{entry.value}" /></f:facet>
<f:facet name="input"><p:inputText value="#{entry.value}" style="width:96%"/></f:facet>
</p:cellEditor>
</p:column>
<p:column style="width:50px" >
<p:rowEditor />
<p:commandButton id="deleteButton" immediate="true" update="#{cc.attrs.panelToUpdate} jobPlanEditionComp:restCallStepEditionComp:restCallStepEditionForm:applyButton"
style="width:15px;height:15px"
action="#{cc.attrs.managedBean.onRemoveParam(cc.attrs.panelId, entry)}" icon="ui-icon-trash" title="Delete"
oncomplete="$('.ui-datatable-data tr').find('span.ui-icon-close').each(function(){this.click()})"
/>
</p:column>
</p:dataTable>
</p:panel>
</composite:implementation>
</ui:composition>
view raw gistfile1.txt hosted with ❤ by GitHub
And finally bean implementation:

public void onRowEdit(RowEditEvent event){
setParamBeingEditable(false);
}
public void onRowEditInit(RowEditEvent event){
setParamBeingEditable(true);
}
public void onRowEditCancel(RowEditEvent event){
setParamBeingEditable(false);
}
public Boolean getParamBeingEditable() {
return paramBeingEditable;
}
public void setParamBeingEditable(Boolean paramBeingEditable) {
this.paramBeingEditable = paramBeingEditable;
}
...
private void onNewQueryParam(){
if(queryParams == null){
queryParams = new ArrayList<RestServiceQueryParam>();
}
RestServiceQueryParam defaultQueryParam = new RestServiceQueryParam();
defaultQueryParam.setKey("key");
defaultQueryParam.setValue("value");
queryParams.add(defaultQueryParam);
}
private void onRemoveQueryParam(RestServiceQueryParam paramToRemove){
queryParams.remove(paramToRemove);
}
view raw View.java hosted with ❤ by GitHub
Notice that Remove button inside third column is in the same line as Edit, Check and Close buttons. This is not a default behaviour - in order to achieve that you need to add following css:

.ui-row-editor:after {
clear: none;
}

1 komentarz: