This question already has answers here:
p:commandbutton action doesn't work inside p:dialog
(4 answers)
Closed 6 years ago.
I have a problem. I have a form
with inputs to be sent to a bean by , the thing is debugged, in the bean object is always null. Could you help me with this.
Here the code:
<h:form id="frmNuevo">
<p:dialog id="dialog" header="AƱadir Presupuesto" widgetVar="dialogNuevo" resizable="true" width="500" height="500" showEffect="fade" hideEffect="explode" modal="true">
<p:growl id="growl" showDetail="true" sticky="true" />
<h:panelGrid id="display" columns="2" cellpadding="4" style="margin: 0 auto;">
<h:outputText value="Diciembre:" />
<p:inputText value="#{presupuestoBean.presupuesto.diciembre}" required="true" maxlength="20" />
<p:commandButton value="Guardar" update=":form:cars, frmNuevo, growl, display" process="#this" actionListener="#{presupuestoBean.insertar}" oncomplete="dialogNuevo.hide()" image="icon-save" />
<p:commandButton value="Cancelar" update=":form:cars" oncomplete="dialogNuevo.hide()" style="margin-bottom: 20px;" image="icon-cancel" />
</h:panelGrid>
<p:separator/></p:dialog>
</h:form>
I tested with SessionScoped and RequestScoped and does not work, the strange thing is I have done other similar beans and if they work
ManagedBean:
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
#ManagedBean(name = "presupuestoBean")
#RequestScoped
public class PresupuestoBean implements Serializable {
private TbPresupuesto presupuesto;
private List<TbPresupuesto> presupuestos;
private UploadedFile file;
private String destination = "C:\\temp\\";
public PresupuestoBean() {
presupuesto = new TbPresupuesto();
presupuestos = new ArrayList();
}
public TbPresupuesto getPresupuesto() {
return presupuesto;
}
public void setPresupuesto(TbPresupuesto presupuesto) {
this.presupuesto = presupuesto;
}
public void prepararInsertar() {
presupuesto = new TbPresupuesto();
presupuestos = new ArrayList();
}
public void insertar() {
PresupuestoDaoImpl presupuestoDao = new PresupuestoDaoImpl();
presupuesto.setPresupuestoId(presupuesto.getLinea().getLineaId());
presupuestoDao.insertar(presupuesto);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Se ha ingresado correctamente"));
presupuesto = new TbPresupuesto();
}
}
The form must go inside the dialog.
<p:dialog>
<h:form>
...
</h:form>
</p:dialog>
The generated HTML representation of the dialog component is namely during page load by JavaScript relocated to the end of <body> in order to improve cross browser compatibility of presenting a modal dialog.
With your current code, this thus means that the dialog will then not sit in a form anymore. So when you try to submit the input values inside the dialog, they will end up as nulls because there is no form in order to collect and send the input values to the server.
Further, you're only processing the submit button inside the command button.
<p:commandButton ... process="#this" />
Remove that attribute. It defaults to #form already, which is exactly what you want.
Related
I use JSF 2.2 and Primefaces 6.1. I have a problem with textarea value on first form submit. I use multiple subviews for one form. The problem is when type something into textarea, after first form submit this value disapear and not update data model. But when type again and fire submit, then this value is showing. The textarea is inside subTable in dataTable.
I tried use valueChangeListener together with ajax. This works, but when click to fast to submit, then value haven't be updated. I tried only ajax but result was the same. I tried valueChangeLister with onchange="submit()" but this not worked. tried solution Primefaces valueChangeListener or <p:ajax listener not firing for p:selectOneMenu but this not working
Textarea code
<h:form id="reuestForm">
<div class="form-group">
<p:dataTable id="edScopeTable" styleClass="form-group dataTable-space"
value="#{requestBean.employeeDealerTabController.getEdScopeCategories()}"
var="category">
<p:columnGroup type="header">
<p:row>
<p:column headerText="#{i18nMsg.ed_env_scopes_tbl_colScope_header}"/>
<p:column headerText="#{i18nMsg.ed_env_scopes_tbl_col_openIdConnect_header}"/>
<p:column headerText="#{i18nMsg.ed_env_scopes_tbl_col_reasonNeeded}"/>
</p:row>
</p:columnGroup>
<p:subTable
value="#{requestBean.employeeDealerTabController.getScopeReasonsByCategory(category)}"
var="edScope" rendered="#{requestBean.employeeDealerTabController.isCategoryInTable(category)}">
<p:column styleClass="#{requestBean.employeeDealerTabController.calculateDiff(edScope,'cell-right')} textAlign-center">
<p:inputTextarea id="reason"
value="#{edScope.reason}" rows="2"
autoResize="false"
data-disable-type="custom"
styleClass="form-control #{edScope.getDiffValue('reason')}"
rendered="#{edScope.edScopeConst.reasonNeeded}"
label="#{i18nMsg.edScope_request_selectionTable_scope_reasonNeeded} #{edScope.edScopeConst.name}"
disabled="#{requestBean.employeeDealerTabController.disableReasonField()}">
<f:attribute name="scope" value="#{edScope}"/>
<f:validateBean
binding="#{requestBean.validatorContainer.requiredBeanValidator}"/>
<p:message for="reason" display="tooltip"/>
</p:inputTextarea>
<h:outputText
rendered="#{not edScope.edScopeConst.reasonNeeded}"
value="#{i18nMsg.edScope_request_selectionTable_scope_noReasonNeeded}"/>
</p:column>
</p:subTable>
</p:dataTable>
</div>
<div class="text-right">
<p:commandButton value="#{(requestBean.request.version eq 1 and requestBean.request.stateDraft) or requestBean.isEdRequestToBePrinted() ? i18nMsg.general_mainButton_send_and_print : i18nMsg.general_mainButton_send}"
id="send"
update="requestForm"
actionListener="#{requestBean.prepareDialog()}"
oncomplete="args.validationFailed ? PF('validationFailedMessageDialog').show() : PF('readyToSendDialog').show(); jQuery(document).scrollTop(0)"
title="#{requestBean.sendButtonDisabled ? i18nMsg.request_sendButtonTooltip : ''}"
styleClass="ui-priority-primary" icon="ui-icon-mail-closed"
disabled="#{requestBean.sendButtonDisabled}" data-disable-type="custom" />
</div>
</h:form>
RequestBean
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class RequestBean extends PageBeanBase implements Serializable {
private EmployeeDealerTabController employeeDealerTabController;
#PostConstruct
public void initialize() {
employeeDealerTabController = new EmployeeDealerTabController();
}
public EmployeeDealerTabController getEmployeeDealerTabController() {
return employeeDealerTabController;
}
public void prepareDialog() {
// preparation before send and show dialog with confirmation send form
}
// rest of method
}
EmployerDealerTabController
public List<EdScopeREason> getScopeReasonsByCategory(int category) {
if(category == 1) {
return scopesOidcList;
} else {
return scopesIdentityList;
}
}
EdScopeReason
#Entity
#Table(name = "ED_SCOPE_REASON")
public class EdScopeReason extends InlineDiffBase<EdScopeReason> implements EdScopeConstBearer, Serializable, Comparable<EdScopeReason> {
private String reason;
#Basic
#Column(name = "REASON")
#NotBlank(groups = RequiredValidationGroup.class, message = "{iamat.validation.general.edScopeReason.notempty}")
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
}
I have setter and getter method. When I debug this value is pass to validator but not set to component. I'm little confused why this value is not set on the first time
EDIT
I add jsf ajax to textarea input and set 5s delay on commandButton. This is some kind of workaround, but still look for better solution. When I use primefaces ajax I don't need delay, but for every primefaces ajax I display loader.gif.
<p:inputTextarea id="reason"
...{requestBean.employeeDealerTabController.disableReasonField()}">
<f:attribute name="scope" value="#{edScope}"/>
<f:validateBean
binding="#{requestBean.validatorContainer.requiredBeanValidator}"/>
<p:message for="reason" display="tooltip"/>
<f:ajax />
</p:inputTextarea>
....
<p:commandButton value="#{(requestBean.request.version eq 1 and requestBean.request.stateDraft) or requestBean.isEdRequestToBePrinted() ? i18nMsg.general_mainButton_send_and_print : i18nMsg.general_mainButton_send}"
id="send"
update="requestForm"
actionListener="#{requestBean.prepareDialog()}"
oncomplete="args.validationFailed ? PF('validationFailedMessageDialog').show() : PF('readyToSendDialog').show(); jQuery(document).scrollTop(0)"
title="#{requestBean.sendButtonDisabled ? i18nMsg.request_sendButtonTooltip : ''}"
styleClass="ui-priority-primary" icon="ui-icon-mail-closed"
disabled="#{requestBean.sendButtonDisabled}" data-disable-type="custom" delay="5000" />
I am not sure if I am making a silly mistake, but this has not been working for me on a very simple case: In my tabview / tabs when I switch from one tab to other I want to save the data that's entered in the form. The Submit button works fine on each tab, but the tabchange event shows all my form data to be null. I have tried process with #all, #form, #this, nothing seems to work. Same with update option.
Here's the XHTML:
<h:form id="form">
<p:growl id="msgs" showDetail="true" keepAlive="5000" />
<p:tabView id="tView" dynamic="true" cache="false" >
<p:ajax event="tabChange" listener="#{deleteMe.onTabChange}" update=":form:msgs" />
<p:tab title="MyTitle I" id="tab1">
<p:fieldset legend="Personal Information" toggleable="false" >
<h:panelGrid columns="2" cellpadding="10">
Value 1: <p:inputText value="#{deleteMe.thingOne}"></p:inputText>
Value 2: <p:inputText value="#{deleteMe.thingTwo}"></p:inputText>
<p:commandButton value="Submit" id="ajax" update=":form:msgs" action="#{deleteMe.onSubmit}" />
</h:panelGrid>
</p:fieldset>
</p:tab>
<p:tab title="MyTitle II" id="tab2">
<p:fieldset legend="Social Information" toggleable="false">
<h:panelGrid columns="2" cellpadding="10">
<p:inputText value="#{deleteMe.thingThree}"></p:inputText>
<p:commandButton value="Submit" id="ajax2" update=":form:msgs" action="#{deleteMe.onSubmit}" />
</h:panelGrid>
</p:fieldset>
</p:tab>
</p:tabView>
</h:form>
And here's my backing bean:
`
import javax.annotation.PostConstruct;
import javax.inject.Named;
import org.primefaces.event.TabChangeEvent;
import org.springframework.context.annotation.Scope;
#Named(value = "deleteMe")
#Scope("view")
public class DeleteBean implements Serializable {
private static final long serialVersionUID = 47L;
private String thingOne;
private String thingTwo;
private String thingThree;
#PostConstruct
public void initialize() {
}
public void onTabChange(TabChangeEvent event) {
System.out.println("Saving draft, current index: "+ event.getTab().getTitle());
System.out.println(thingOne);
System.out.println(thingTwo);
saveDraft();
}
public void onSubmit() {
System.out.println(thingOne);
System.out.println(thingTwo);
System.out.println(thingThree);
saveDraft();
}
public void saveDraft() {
System.out.println("This is thing 1 value: "+thingOne);
System.out.println("This is thing 2 value: "+thingTwo);
System.out.println("This is thing 2 value: "+thingThree);
}
public String getThingOne() {
return thingOne;
}
public void setThingOne(String thingOne) {
this.thingOne = thingOne;
}
public String getThingTwo() {
return thingTwo;
}
public void setThingTwo(String thingTwo) {
this.thingTwo = thingTwo;
}
public String getThingThree() {
return thingThree;
}
public void setThingThree(String thingThree) {
this.thingThree = thingThree;
}
}
`
On tabchange event, it triggers the method, but the values are all null.
SystemOut O This is thing 1 value: null
SystemOut O This is thing 2 value: null
SystemOut O This is thing 2 value: null
Can you please point out if I am making some silly mistake? Thank you.
The correct answer is to use skipChildren="false" on your p:ajax commands.
https://github.com/primefaces/primefaces/issues/2525
<p:ajax event="tabChange"
skipChildren="false"
listener="#{deleteMe.onTabChange}"
update=":form:msgs" />
I have the same problem.
On changing the tab without submitting, data will be lost because of not updating the input text field. You can add ajax for Input text field.
<p:inputText id="thingOneId" value="#{deleteMe.thingOne}">
<p:ajax update="thingOneId"/>
</p:inputText>
skipchildren="true"
works for not loosing the data, but it won't update the value from inputfields.
Saw a workaround for it but I am not sure why it is working this way:
I had to add the remote command with a tabchange listener on tabView.
<p:remoteCommand name="onTabChangeProcess" process="tView, #this"/>
<p:tabView activeIndex="#{deleteMe.activeIndex}" id="tView" onTabChange="onTabChangeProcess()">
<p:ajax event="tabChange" listener="#{deleteMe.onTabChange}" update="tView" process="tView"/>
This made the form to work as expected.
I'm using STS (Spring tool suite) with spring boot, primefaces and hibernate.
I have an page with a p:datatable. In the last column, have a p:commandbutton for edit data of the table (p:dialog).
When I open the dialog, all data load correct. If I close de dialog without save and open other line of the table data load correct again, but, if I save the data and open a new dialog of other line of the table, the field p:selectOneMenu is loaded with wrong data. Your value is the same value of the last dialog saved. All dialog data has correct, less the combobox (p:selectOneMenu). In debug, the value returned in backing bean is correct.
Some things I've tried:
Changed p:commandbutton to p:commandlink;
In button "save" of dialog, "update" field with the p:panel of table, the h:form, h:datable;
Change onComplete to onClick;
Use h:selectOneMenu instead of p:selectOneMenu;
Downgrade primefaces (currently 6.1) and myfaces (currently 2.2.12).
All no sucess.
ps: Datatable is filtered and paginated.
xhtml:
<p:panel id="pnlData" header="My Table">
<h:form id="frmTable">
<p:dataTable var="item" value="#{RSDMBean.myData}"
id="tblTicketsID" widgetVar="tabelaTickets" some things of pagination and filters here...>
<p:column />
<p:column /> ...
<p:column headerText="Edit">
<p:commandButton value="Edit"
actionListener="#{RSDMBean.editTicketLoad(item.idTicket)}"
update=":formPnl:pnlTkct" oncomplete="PF('dlgtkt').show();">
</p:commandButton>
</p:column>
</p:datatable>
</h:form
</p:panel>
<p:dialog id="dlgtktID" header="Edit ticket" widgetVar="dlgtkt"
modal="true">
<h:form id="formPnl">
<h:panelGrid id="pnlTkct" columns="2" cellpadding="10"
cellspacing="1" style="absolute">
<h:outputText style="font-weight:bold" value="Id Ticket: " />
<h:outputText value="#{RSDMBean.ticketEdited.id}" />
Others fields here...
<h:outputText style="font-weight:bold" value="County: " />
<p:selectOneMenu style="min-width: 162px;" required="true">
<f:selectItem itemLabel="#{RSDMBean.ticketEdited.county.name}"
itemValue="#{RSDMBean.ticketEdited.county.id}" />
<f:selectItems
value="#{RSDMBean.countyItensedit.entrySet()}" var="entry"
itemValue="#{entry.key}" itemLabel="#{entry.value}" />
</p:selectOneMenu>
<p:commandButton value="Save" action="#{RSDMBean.saveEdit}"
update=":frmTable:tblTicketsID" oncomplete="PF('dlgtkt').hide();" />
end tags here...
Bean:
import javax.annotation.PostConstruct;
import javax.faces.bean.RequestScoped;
import org.springframework.beans.factory.annotation.Autowired;
.
.
.
#Controller("RSDMBean")
#RequestScoped
public class MyMBean implements Serializable {
#Autowired
private ResiduoService residuoService;
#Autowired
private ResiduoRepository residuoRepository;
#Autowired
private CountyRepository countyRepository;
private Residuo ticketEdited;
private List<County> county;
private Map<Long, String> countyItensEdit = new HashMap<Long, String>();
public void editTicketLoad(String param) {
long idTicket = Long.parseLong(param);
ticketEdited = residuoRepository.findOne(idTicket);
county = countyRepository.findAll();
}
#PostConstruct
public void construct() {
//some loads database here...
county = countyRepository.findAll();
if (countyItensEdit.isEmpty()) {
for (Municipio c : countyItensEdit) {
countyItensEdit.put(c.getId(), c.getNome());
}
}
}
In p:selectOneMenu was missing value tag:
<p:selectOneMenu style="min-width: 162px;" required="true"
value="#{RSDMBean.ticketEdited.county.id}">
I want to call Java method from Primefaces dialog. I tested this code:
<h:form>
<p:dialog header="New Sensor" widgetVar="dlg" focus="name" modal="true" showEffect="fade">
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="name" value="Name" />
........
<p:inputText id="enabled" label="enabled" value="#{newSensor.sensor.enabled}" />
</h:panelGrid>
<f:facet name="footer">
<p:commandButton id="ajax" value="Create Sensor" styleClass="ui-priority-primary" type="button" actionListener="#{newSensor.saveRecord()}"/>
</f:facet>
</p:dialog>
</h:form>
Java bean:
#Named
#RequestScoped
public class NewSensor implements Serializable
{
private SensorObj sensor = new SensorObj();
public SensorObj getSensor()
{
return sensor;
}
public void setSensor(SensorObj sensor)
{
this.sensor = sensor;
}
public void saveRecord(){
System.out.println(">>>>>>>!!!!!! " + sensor.getName());
}
}
Wehn I click the button nothing happens. Can you give some advice how I can fix this issue?
You should remove type="button" in your commandButton because it will prevent the button from sending a request.
Additionally, you are using actionListener in your commandButton.
Your method in the bean should have ActionEvent as its parameter.
public void saveRecord(ActionEvent actionEvent) {
System.out.println(">>>>>>>!!!!!! " + sensor.getName());
}
Please refer here for additional information.
I am trying to pass a parameter (a user's id from a datatable) from one page to the next where I am using it (showing the user's details). The problem is that I can not get it. What am I missing? What am I doing wrong? I am using PrimeFaces 5 and JSF 2.2 (also Hibernate 4). Is there any way that I can have the parameter #PostConstruct so that I can load the user's details immediately?
The first page with the datable
<h:form id="manageUserForm" prependId="false">
<p:growl id="messages" showDetail="true" life="20000"/>
<p:dataTable id="usersTable" var="user" value="#{manageUsers.users}">
<f:facet name="header">
#{pvtmsg.registeredUsers}
</f:facet>
<p:column headerText="ID">
<h:outputText value="#{user.id}" />
</p:column>
<p:column headerText="#{pvtmsg.username}">
<h:outputText value="#{user.username}" />
</p:column>
<p:column headerText="#{pvtmsg.firstname}">
<h:outputText value="#{user.firstname}" />
</p:column>
<p:column headerText="#{pvtmsg.lastname}">
<h:outputText value="#{user.lastname}" />
</p:column>
<p:column headerText="#{pvtmsg.email}">
<h:outputText value="#{user.email}" />
</p:column>
<p:column headerText="#{pvtmsg.status}">
<h:outputText value="#{user.enabled ? pvtmsg.enabled : pvtmsg.disabled}" />
</p:column>
<p:column style="width:32px;text-align: center">
<p:commandLink action="editUser.xhtml?faces-redirect=true">
<f:setPropertyActionListener value="#{user.id}" target="#{manageUsers.selectedUser}" />
<f:param name="userId" value="#{manageUsers.selectedUser}" />
</p:commandLink>
</p:column>
</p:dataTable>
</h:form>
Its backing bean
package beans;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import models.User;
import utils.PropertyHelper;
#Named(value = "manageUsers")
#ViewScoped
public class ManageUsers implements Serializable {
private static final long serialVersionUID = 954672295622776147L;
private List<User> users = null;
private String selectedUser = null;
public ManageUsers() {
try {
PropertyHelper helper = new PropertyHelper();
users = helper.getUsers();
} catch (Exception ex) {
Logger.getLogger(ManageUsers.class.getName()).log(Level.SEVERE, null, ex);
}
}
public List<User> getUsers() {
return users;
}
public String getSelectedUser() {
return selectedUser;
}
public void setSelectedUser(String selectedUser) {
this.selectedUser = selectedUser;
}
}
The second page
<f:metadata>
<f:viewParam name="userId" value="#{editUserBean.userId}" />
</f:metadata>
<h:form id="editUserForm" prependId="false">
<p:growl id="messages" showDetail="true" life="20000"/>
<!--nothing yet-->
</h:form>
Its backing bean
package beans;
import java.io.Serializable;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named(value = "editUserBean")
#ViewScoped
public class EditUserBean implements Serializable {
private static final long serialVersionUID = 543216875622776147L;
private String userId;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
Your commandLink doesn't make sense here. Typically when you want to navigate with a commandLink, you should do a redirect in your backing bean.
If you want to navigate using outcome, then something like this should work for you:
<h:link outcome="editUser.xhtml">
<f:param name="userId" value="#{user.id}" />
</h:link>
So I found my solution here http://www.oracle.com/technetwork/articles/java/jsf22-1377252.html and, after some time, the last piece that I needed here here http://www.coderanch.com/t/625319/JSF/java/working-viewParam
Your f:viewParams won't be available during the #PostConstruct method call. You should assign a f:viewAction, since you are using JSF 2.2, to handle business processing on GET parameters.
<f:metadata>
<f:viewParam name="userId" value="#{editUserBean.userId}" />
<f:viewAction action="#{editUserBean.processUserId}"/>
</f:metadata>
See also:
Read this if using JSF older than 2.2
JSF bean: call #PostConstruct function after ViewParam is set