Check any celleditor in a data table is in edit mode - jsf-2

I have a data table displying some application parameters having 3 columns:
name (outputext),
value (p:cellEditor) and
edit (p:rowEditor used)
On clicking edit button in any row value field converts into input field and is having validator attached. After changing and accepting( clicking check icon) values an 'update button' is provided at the bottom of page to save all changes.
My problem is if a validation error comes and we press 'update button' then call goes to save function in managed bean with old value. So to stop this I want to disable 'update button' when any row is having edit mode opened. Can I check the mode of all cell editors in column 2 , so I will use that in disabled attribute of update button.
Please do suggest any other better way is also possible ?
Using a jsf 2.1 and primefaces 3.5
XHTML snippet
<!-- Body panel for display of individual configuration mode -->
<p:panel id="mainConfigPanel" >
<!-- status message section -->
<p:messages id="msg" autoUpdate="true" closable="true"/>
<!-- Parameter configuration mode -->
<p:panel
rendered="#{configMBean.configUtility.configParamModeOn}"
styleClass="panelNoBorder">
<p:dataTable id="configParamTable" var="configParamVar"
value="#{configMBean.configParamList}" editable="true">
<p:ajax event="rowEdit" listener="#{configMBean.onRowEdit}" update=":mainForm:msg" />
<p:ajax event="rowEditCancel" listener="#{configMBean.onRowCancel}" update=":mainForm:msg" />
<p:column headerText="Parameter Name" sortBy="#{configParamVar.paramConfigName}">
<h:outputText id="paramNameId" value="#{configParamVar.paramConfigName}" />
</p:column>
<p:column headerText="Param Value" sortBy="#{configParamVar.paramConfigValue}">
<p:cellEditor>
<f:facet name="output" > <h:outputText value="#{configParamVar.paramConfigValue}" /> </f:facet>
<f:facet name="input">
<p:inputText id="paramValueId" value="#{configParamVar.paramConfigValue}" required="true"
validator="#{configMBean.validateParam}" >
<f:validateLength maximum="2000" />
<f:attribute name="input" value="#{configParamVar}" />
</p:inputText>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Edit" style="text-align:center;vertical-align:top;width:20px">
<p:rowEditor />
</p:column>
</p:dataTable>
<h:panelGrid columns="2" >
<p:commandButton value="Update Parameters" actionListener="#{configMBean.saveParamUpdate}" update=":mainForm" />
<p:commandButton value="Cancel" actionListener="#{configMBean.cancelParamUpdate}" immediate="true" update=":mainForm">
</p:commandButton>
</h:panelGrid>
</p:panel>
<!-- End of Parameter configuration mode panel -->
</p:panel>
<!-- End of body panel for individual configuration mode -->
</p:panelGrid>
<!-- end of main panel -->
Functions in Managed Bean
public void onRowEdit(RowEditEvent event) {
System.out.println(" In Row Edit");
}
public void onRowCancel(RowEditEvent event) {
System.out.println("In Row Canel of Parameter Config");
}
public void validateParam(FacesContext facesContext, UIComponent component,
Object value) throws ValidatorException, Exception {
if (value != null) {
//Getting parameter Name and Value for validation
String paramName = ((RowEntity) component.getAttributes().get("input")).getParamConfigName();
String paramValue = (String) value;
FacesMessage msg = null;
//Validation Cases
if (paramName.equalsIgnoreCase(ResourceBundle.getMsg("Param_Enable_FTP"))) {
if (!paramValue.equalsIgnoreCase("true") || !paramValue.equalsIgnoreCase("false")) {
msg = new FacesMessage(FacesMessage.SEVERITY_WARN, ResourceBundle.getMsg("Param_True_False_Validation")+ paramName, "");
throw new ValidatorException(msg);
}
} else if (paramName.equalsIgnoreCase(ResourceBundle.getMsg("Param_Contingency_Reserve"))) {
if (!Pattern.matches("-?\\d*\\.?\\d*", paramValue)) {
msg = new FacesMessage(FacesMessage.SEVERITY_WARN, ResourceBundle.getMsg("Param_Number_Validation") + paramName, "");
throw new ValidatorException(msg);
}
}// end if else if
}
}

From the docs: There is an Ajax Behavior Event for rowEdit
rowEdit | org.primefaces.event.RowEditEvent | When a row is edited.
You could disable the update button when the RowEditEvent got fired and release the button after the row editing was canceled or saved.
I Hope I got your question right and this helps.

Related

Show/Hide components in primefaces 5/JSF 2.2 [duplicate]

This question already has an answer here:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?
(1 answer)
Closed 7 years ago.
I thought this would be easy but I just cannot get it. I have a drop down and based on selection, I should be able to show/Hide another drop down based on a boolean. By default the boolean is false and only when it is true should the second drop down be rendered:
My page:
<h:outputLabel value="Select Report: "/>
<p:selectOneMenu value="#{daily.reportname}" id="sector" style="width: 250px;">
<f:selectItem itemLabel="ALL" itemValue="ALL" />
<f:selectItems value="#{daily.reportType()}"/>
<p:ajax event="change" update="branchrender" listener="#{daily.selectedReport()}" />
</p:selectOneMenu>
<h:panelGroup id="branchrender" rendered="#{daily.showBranchDimension}">
<h:outputText value="Branch" />
<p:selectOneMenu value="#{accounts.branchs}" id="branch" style="width: 250px;">
<f:selectItem itemLabel="ALL" itemValue="ALL" />
<f:selectItems value="#{dimensions.branchCode()}"/>
</p:selectOneMenu>
</h:panelGroup>
My selected report Method:
public void selectedReport() {
if (reportname.startsWith("cust_")) {
custrepname = reportname;
useBranch = pr.getCustRepProperties(custrepname + ".bi").getProperty("bi.useBranchDim");
showBranchDimension = useBranch.equalsIgnoreCase("true");
System.out.println("HERE: " + showBranchDimension);
} else {
custrepname = null;
}
}
showBranchDimension is a boolean having getter and setter:
public boolean isShowBranchDimension() {
return showBranchDimension;
}
public void setShowBranchDimension(boolean showBranchDimension) {
this.showBranchDimension = showBranchDimension;
}
Am I missing something? The System.out.println prints true but the component is NOT rendered.
You have to make the rendered component a rendered free because it must be exist when you submit the ajax request to server add another container to branchrender and move the rendered id to it
<h:panelGroup id="branchrender">
<h:panelGroup rendered="#{daily.showBranchDimension}">
<h:outputText value="Branch" />
<p:selectOneMenu value="#{accounts.branchs}" id="branch" style="width: 250px;">
<f:selectItem itemLabel="ALL" itemValue="ALL" />
<f:selectItems value="#{dimensions.branchCode()}"/>
</p:selectOneMenu>
</h:panelGroup>
</h:panelGroup>
See more about this.
I think problem could be with the way your implemented the p:ajax component. See the comments of p:ajax listener method not invoked.

<p:growl> not executing on <p:wizard> FlowListener

I have a JSF page that contains a growl message with primefaces Wizard component. The Wizard contains a FlowListener attribute. On the Flowevent, the growl message should fire however it is not. The FlowListener is working because code not related to updating the growl message is being executed however the growl message is not being displayed. Any help in fixing this is appreciated.
Using: JSF Mojarra 2.2, Primefaces 4.0, Galssfish 4
My JSF code:
<h:form>
<p:growl id="growl" showDetail="true" />
<p:wizard flowListener="#{reviewBean.handleFlow}" >
<p:tab id="Contact" title="Contact Details" >
<p:panel header="#{reviewBean.contactInstr}" >
<p:messages />
<h:panelGrid columns="2" >
<h:outputText value="Address: " />
<p:inputText value="#{reviewBean.contactData.address1}" required="true"
requiredMessage="Address is required" size="50" />
<h:outputText value="Address: " />
<p:inputText value="#{reviewBean.contactData.address2}" size="50" />
<h:outputText value="City: " />
<p:inputText value="#{reviewBean.contactData.city}" required="true"
requiredMessage="City is required" size="50"/>
<h:outputText value="State: " />
<p:selectOneMenu value="#{reviewBean.contactData.state}" >
<f:selectItems value="#{reviewBean.contactData.stateOptions}" />
</p:selectOneMenu>
<h:outputText value="Zip: " />
<p:inputText value="#{reviewBean.contactData.zip}" required="true"
requiredMessage="Zip is required" size="50" />
</h:panelGrid>
</p:panel>
</p:tab>
// Additional tabs omitted .........
</p:wizard>
</h:form>
FlowListener from my Bean:
public String handleFlow(FlowEvent event) {
String currentStepId = event.getOldStep(); // get current tab
String stepToGo = event.getNewStep(); // get next tab in Flow
RequestContext request = RequestContext.getCurrentInstance();
FacesContext context = FacesContext.getCurrentInstance();
switch (currentStepId) {
case "Contact":
// Save user entered contact information to database
datalist.saveContact(contactData, user.getId());
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Data Saved", "") );
request.update("growl");
break;
// remaining cases omitted ........
}
return stepToGo; // return next tab in Flow
}
request.update("growl");
This is the wrong part.
Put an id to your form, then reference it like
i.e
request.update("your_form_id:growl");
Alternatively you could activate the auto-update feature of the growl with the attribute autoUpdate="true" of the growl component, and remove the request.update() method call in your backing bean.

p:selectOneMenu changed when tab is changed

I have a Primefaces dialog, and inside it there is a tabView. In this tabView I have 3 tabs, each one called towards ui:include. In the first tab I have a selectOneMenu which defines a property called tipoProprietario from class ProprietarioORM. The navigation between tab is done not by tabs themselves (in this stage they're disabled) but towards commandButtons at bottom of dialog. When I click in a commandButton to pass from the first to second tab tipoProprietario is filled correctly. However, when I click to pass from second do third tab (or even to the first one), I found that the selectItem value is changed to null. Consequently, the tipoProprietario property is also changed to null. Debugging, I saw that first it is called the Select Item listener method and after the tipoProprietario setter.
Can someone explain why this it is happening? How to correct it?
dialog.xhtml
<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:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<p:dialog id="dlgEdicao" widgetVar="dlgEdicao" resizable="false"
closable="true" modal="true" closeOnEscape="true"
header="#{(proprietarioMB.edicao)? msg['proprietario.titulo.editar']: msg['proprietario.titulo.incluir']}">
<p:tabView id="tabEdicao" widgetVar="tabEdicao" dynamic="true"
styleClass="tabEdicaoProprietario" cache="false"
binding="#{proprietarioMB.tabEdicao}">
<p:tab id="tabProprietario" title="#{msg['proprietario.titulo']}"
disabled="#{not proprietarioMB.edicao}" titleStyleClass="">
<ui:include src="./aba_proprietario.xhtml" />
</p:tab>
<p:tab id="tabEnderecoContato"
title="#{msg['proprietario.titulo.aba.endereco']}"
disabled="#{not proprietarioMB.edicao}">
<ui:include src="./aba_endereco_contato.xhtml" />
</p:tab>
<p:tab id="tabVeiculo"
title="#{msg['proprietario.titulo.aba.veiculo']}"
disabled="#{not proprietarioMB.edicao}">
<ui:include src="./aba_veiculo.xhtml" />
</p:tab>
</p:tabView>
<f:facet name="footer">
<p:commandButton id="btnDialogoAnterior"
value="#{msg['titulo.anterior']}"
rendered="#{not proprietarioMB.edicao}" immediate="true"
disabled="#{not proprietarioMB.btnAnteriorHabilitado}"
actionListener="#{proprietarioMB.doEventClickBtnAnterior}"
update="#this tabEdicao btnDialogoSeguinte btnDialogoConcluir"
style="margin-right: 20px;" />
<p:commandButton id="btnDialogoSeguinte"
value="#{msg['titulo.proximo']} #{(not proprietarioMB.btnConcluirVisivel)? '': 'display: none;'}"
rendered="#{not proprietarioMB.edicao}"
actionListener="#{proprietarioMB.doEventClickBtnSeguinte}"
update="#this tabEdicao btnDialogoAnterior btnDialogoConcluir"
style="margin-right: 20px; #{(not proprietarioMB.btnConcluirVisivel)? '': 'display: none;'}" />
</f:facet>
</p:dialog>
</ui:composition>
aba_proprietario.xhtml (the first tab)
<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:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<p:panel id="pnlDadosProprietario">
<p:focus for="selTipoEdicao" />
<p:fieldset id="fieldDadosProprietario"
legend="#{msg['proprietario.titulo']}"
rendered="#{not empty proprietarioMB.proprietario}">
<p:panelGrid id="pnlDadosProprietarioEdicao">
<p:row>
<p:column>
<p:outputLabel id="lblTipoEdicao"
value="#{msg['proprietario.titulo.tipo']}" for="selTipoEdicao" />
</p:column>
<p:column>
<p:selectOneMenu id="selTipoEdicao"
value="#{proprietarioMB.proprietario.tipoProprietario}"
valueChangeListener="#{proprietarioMB.doEventTipoDocumentoPesquisaChanged}"
immediate="true">
<f:selectItems value="#{proprietarioMB.tiposProprietarios}" />
<p:ajax event="change" update="txtDocumentoEdicao" />
</p:selectOneMenu>
</p:column>
<p:column>
<p:outputLabel id="lblDocumentoEdicao"
value="#{msg['proprietario.titulo.documento']}"
for="txtDocumentoEdicao" />
</p:column>
<p:column>
<p:inputMask id="txtDocumentoEdicao"
value="#{proprietarioMB.proprietario.documento}"
mask="#{proprietarioMB.mascaraDocumento}" />
</p:column>
</p:row>
</p:panelGrid>
</p:fieldset>
</p:panel>
</ui:composition>
The Managed Bean
#ManagedBean
#ViewScoped
public class ProprietarioMB {
private static final String MASCARA_CPF = "999.999.999-99";
private static final String MASCARA_CNPJ = "99.999.999/9999-99";
private static final SelectItem[] tiposProprietarios = new SelectItem[] {
new SelectItem(JURIDICA, JURIDICA.getDescricao()),
new SelectItem(FISICA, FISICA.getDescricao()), };
private ProprietarioORM proprietario;
private String mascaraDocumento;
private TabView tabEdicao;
/**
* Select Item listener method: Changes inputMask mask
*/
public void doEventTipoDocumentoPesquisaChanged(ValueChangeEvent event) {
this.mascaraDocumento = (event.getNewValue() == FISICA) ? MASCARA_CPF
: MASCARA_CNPJ;
}
public void doEventClickBtnAnterior() {
System.out.println("ProprietarioMB.doEventClickBtnAnterior(): "
+ this.tabEdicao.getActiveIndex());
this.tabEdicao.setActiveIndex(this.tabEdicao.getActiveIndex() - 1);
}
public void doEventClickBtnSeguinte() {
System.out.println("ProprietarioMB.doEventClickBtnSeguinte(): "
+ this.tabEdicao.getActiveIndex());
System.out.println("ProprietarioMB.doEventClickBtnSeguinte(): "
+ this.proprietario);
if (this.tabEdicao.getActiveIndex() == 0) {
if (this.validarProprietario()) { // Validation method
this.tabEdicao.setActiveIndex(1);
}
} else if (this.tabEdicao.getActiveIndex() == 1) {
this.tabEdicao.setActiveIndex(2);
}
}
// Other methods + getters & setters
}
ProprietarioORM
public class ProprietarioORM {
private String nome;
private TipoProprietarioEnum tipoProprietario;
// getters & setters
}
It's most likely because of the binding="#{proprietarioMB.tabEdicao}"
For one thing, you don't appear to need the binding at all. Even if you did, you failed to initialize the component in your backing bean, a bug that'll result in the <p:tabView/> attempting to bind to a null variable tabEdicao.
As you don't appear to be using the tabview variable in the backing bean, my recommendation would be to get rid of it. If you really need it, just initialize it:
private TabView tabEdicao = new TabView();
Kolossus:
This issue was resolved when I added the attibute dynamic="true" to dialog. Actually, the real value was dynamic=#{empty proprietarioMB.proprietario}, because I was geting NullPointerException when loading the page. proprietario property is loaded towards #PostConstruct method.

form rendered on primefaces isn't calling the manage bean

I'm having problems with a form that is rendered by a booleanButtom on PrimeFaces 3.5
the form appear as expected but when I commit the values of the field come null.
The code of the pag:`
<p:panelGrid>
<p:row>
<p:column>
<h:form id="city">
<p:panelGrid columns="2">
<h:outputText value="Name: "/>
<p:inputText label="Name" value="#{managedBean.city.name}"/>
<h:outputText value="Status: "/>
<p:selectBooleanButton value="#{managedBean.city.status}" onLabel="Enable" offLabel="Disable">
<p:ajax listener="#{managedBean.changeStatusCity()}"/>
</p:selectBooleanButton>
<h:outputText value="Add neighborhood?"/>
<p:selectBooleanButton id="btAddNeighborhood" value="#{managedBean.addNeighborCity}" onLabel="Cancel" offLabel="Yes">
<p:ajax update=":addNeighbor" listener="#{managedBean.addNeighborCity()}"/>
</p:selectBooleanButton>
</p:panelGrid>
</h:form>
</p:column>
</p:row>
<p:row>
<p:column>
<h:form id="addNeighbor">
<p:panel header="Neighborhood" rendered="#{managedBean.addNeighborCity}">
<p:panelGrid columns="2">
<h:outputText value="Name: "/>
<p:inputText label="Name" value="#{managedBean.neighborhood.name}"/>
<h:outputText value="Status: "/>
<p:selectBooleanButton value="#{managedBean.neighborhood.status}" onLabel="Enable" offLabel="Disable" onIcon="ui-icon-check" offIcon="ui-icon-close">
<p:ajax listener="#{managedBean.changeStatusNeighbor()}"/>
</p:selectBooleanButton>
</p:panelGrid>
</p:panel>
</h:form>
<h:form id="formBt">
<p:commandButton id="bt" value="Add" actionListener="#{managedBean.saveNeighborCity()}" update=":addNeighbor, :city:btAddNeighborhood"/>
</h:form>
</p:column>
</p:row>
</p:panelGrid>`
And the manage bean
public void addNeighborCity(){
if(addNeighborCity){
neighborhood = new Neighborhood();
neighborhood .setStatus(true);
neighborhood .setStringStatus("Enable");
}else{
neighborhood = null;
}
}
public void changeStatusNeighbor() {
if (neighborhood .isStatus()) {
neighborhood .setStringStatus("Enable");
} else {
neighborhood .setStringStatus("Disable");
}
}
public void saveNeighborCity(){
city.getNeighborhoods().add(neighborhood );
neighborhood = null;
addNeighborCity = false;
}
All the input inside of the form that was rendered doesn't send the information to the manage bean and when I put the button that add the neighbor to the list of the city the button stop working and doesn't call the manage bean any more.
Does someone knows what I'm doing wrong or what is happening.
I'm using Primefaces3.5, GlassFish4.0 and JSF2.2
As you did not post the whole managed bean, I guess that you're using the default scope of the managed bean: #RequestScoped. In that case you should use #ViewScoped.
I solved the problem, I was using glassfish 4 and it forces the jsf2.2 even when you put the jsf2.1 in our project, then I changed to glassfish 3 and all work just fine, thanks for the answers, and I'm using #ScopeSession.

Update view parameter without redirecting the page

Is it possible to update view parameter without redirecting the page? For instance
I have a managed bean which checks if an ID exist
public void signIn(){
Client c = clientFacade.loginDetail(client.getID());
if (c != null) {
loggedIn = true;
}
else{
loggedIn = false;
}
}
and a view which renders just fine if the ID exist.
<h:panelGroup rendered="#{not applicationManager.loggedIn}">
<p:commandLink value="Sign In" onclick="loginDialog.show()" styleClass="login-link"></p:commandLink>
</h:panelGroup>
<h:panelGroup rendered="#{applicationManager.loggedIn}">
<p:menuButton value="#{applicationManager.client.firstname}" />
</h:panelGroup>
<p:dialog widgetVar="loginDialog" >
<h:panelGrid columns="2" cellpadding="5">
ID : <p:inputText value="#{applicationManager.client.id}" />
<p:commandButton value="submit" action="#{applicationManager.signIn()}" update=":loginForm" />
</h:panelGrid>
</p:dialog>
Is it possible to insert the code below at the top of the view and still have an update on the url?
<f:metadata>
<f:viewParam name="input" value="#{applicationManager.client.id}" />
<f:event listener="#{applicationManager.signIn()}" type="preRenderView"/>
</f:metadata>
I tried it, but it's not working, so I guess I might be missing something or doing something wrong.

Resources