InputText field in the following dialog retains previous value even though I set it to blank before calling show(). The inputText field is only displayed blank when show() is called for the first time. My bean is session scoped.
<p:dialog id="dlgId" widgetVar="dlgVar" dynamic="true">
<h:form>
<h:panelGrid columns="1">
<h:outputLabel for="nametext" value="Name" />
<p:inputText id="nametext" value="#{myBean.name}" />
</h:panelGrid>
<p:commandButton value="Save" actionListener="#{myBean.saveAction}" />
</h:form>
public void add(TreeNode selectedTreeNode) {
setName("");
RequestContext.getCurrentInstance().execute("PF('dlgVar').show()");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
How can I get the inputTEext field to display the value I set before calling show() rather then the value previously entered by the user?
The thing is: you need to update your form. To make it, you can use one of these solutions.
Solution 1 : update it from your xhtml
<h:form id="form">
<h:panelGrid columns="1">
<h:outputLabel for="nametext" value="Name" />
<p:inputText id="nametext" value="#{myBean.name}" />
</h:panelGrid>
<p:commandButton value="Save" actionListener="#{myBean.saveAction}" update=":form" />
</h:form>
Solution 2 : update it from your managedBean
YourXhtml
<h:form id="form">
...
</h:form>
YourManagedBean
public void saveAction() {
...
name = "";
RequestContext.getCurrentInstance().update(":form");
}
You can also read this post Can I update a JSF component from a JSF backing bean method?.
Solution 3 : update it using an Ajax event
You can also add an ajax event
<p:commandButton value="Save" type="button" >
<p:ajax event="click" listener="#{myBean.saveAction}" update=":form"/>
</p:commandButton>
Related
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 create edit form for Primefaces table. I tested this code:
<h:form id="form">
<p:dataTable id="tbl" var="systemuser" value="#{systemusers.systemUsers}"
selectionMode="single" selection="#{systemusers.selectedSystemUser}" rowKey="#{systemuser.username}" lazy="true"
resizableColumns="true"
>
<p:ajax event="rowSelect" listener="#{systemusers.onRowSelect}" update=":form:carDetail" oncomplete="PF('carDialog').show()" />
....................
</p:dataTable>
<p:dialog id="wd" header="System User Details" widgetVar="carDialog" modal="true" showEffect="fade" hideEffect="fade" resizable="true">
<p:outputPanel id="carDetail" style="text-align:center;">
<p:panelGrid columns="2" columnClasses="label,value">
<h:outputLabel for="id" value="ID" />
<p:outputLabel id="id" value="#{systemusers.selectedSystemUser.id}" rendered="#{not systemusers.editable}"/>
<h:inputText value="#{systemusers.selectedSystemUser.id}" rendered="#{systemusers.editable}" />
........
</p:panelGrid>
</p:outputPanel>
<f:facet name="footer">
<p:commandButton value="Edit System User" rendered="#{not systemusers.editable}"
actionListener="#{systemusers.editRecord(false)}">
<f:ajax render=":form:wd" execute=":form:wd"></f:ajax>
</p:commandButton>
<p:commandButton value="Cancel" rendered="#{systemusers.editable}" actionListener="#{systemusers.editRecord(true)}">
<f:ajax render=":form" execute=":form"></f:ajax>
</p:commandButton>
</f:facet>
</p:dialog>
<p:contextMenu for="tbl">
<p:menuitem value="View" update="carDetail" icon="fa fa-search" oncomplete="PF('carDialog').show()"/>
<p:menuitem value="Delete" update="tbl" icon="fa fa-remove" actionListener="#{systemusers.deleteSystemUser}">
<p:confirm header="Confirmation" message="Are you sure?" icon="fa fa-warning" />
</p:menuitem>
</p:contextMenu>
<p:confirmDialog global="true" showEffect="fade" hideEffect="fade">
<p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="fa fa-check" />
<p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="fa fa-remove" />
</p:confirmDialog>
</h:form>
Managed bean:
#Named
#RequestScoped
public class Systemusers implements Serializable
{
.......
public void editRecord(boolean editable)
{
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session = factory.getCurrentSession();
try
{
session.getTransaction().begin();
SystemUsersModel obj = new SystemUsersModel();
obj.setId(selectedSystemUser.getId());
..........
session.update(obj);
session.getTransaction().commit();
this.editable = editable;
}
catch (Exception e)
{
e.printStackTrace();
session.getTransaction().rollback();
}
}
......
private boolean editable = false;
public boolean isEditable()
{
return editable;
}
public void setEditable(boolean editable)
{
this.editable = editable;
}
}
When I open the Edit form and I click button Edit System User the form disappears. Probably because I render and execute it. How I can execute the form and under it without closing it?
The example code is bad in multiple ways. Two things stand out:
It is not an [mcve]
<f:ajax render=":form" execute=":form"> is superfluous or might even cause the weird behaviour
OP most likely does not know that (quote from the PrimeFaces showcase , emphasis mine)
CommandButton
CommandButton extends the standard h:commandButton with ajax, partial processing and skinning features.
So the commandBotton is already ajax anabled and does not need to hava a
<f:ajax render=":form" execute=":form">
inside it. This (most likely) makes an the update run twice. One #none (Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes) and one updating the form. The second one most likely does not have any content. But trying (and debugging) will make things clear. If this is not the answer, the reason cannot be seen in the code and hence it should have been a [mcve]
I am attempting to create a dialog that will serve the purpose of both creating objects and updating them. So if I happen to click the 'new' button I will be presented a dialog containing empty fields to be filled or if I click on an edit button for an entry, that entry's data will presented in the dialog for update.
Following the example in the primefaces showcase for version 5.2, I can present the data in a read only outputText form, however when I change it to an inputText, the field remains empty. The following code is an example of what I have:
<h:form id="form">
<p:dataGrid id="guestList" var="guest" value="${guestList.guests}" columns="3" paginator="true" rows="20">
<f:facet name="header">
Guest List
</f:facet>
<p:panel>
<h:outputText value="${guest.name}" />
<br />
<h:outputText value="${guest.street}" />
<br />
<h:outputText rendered="#{guest.street2.length() gt 0}"
value="${guest.street2}" />
<h:panelGroup rendered="#{guest.street2.length() gt 0}">
<br />
</h:panelGroup>
<h:outputText value="${guest.city}, " />
<h:outputText value="${guest.state} " />
<h:outputText value="${guest.zipCode}" />
<p:commandButton update="#form:newGuestDetail" oncomplete="PF('newGuestDialog').show()" icon="ui-icon-edit" styleClass="ui-btn-inline">
<h:outputText styleClass="ui-icon ui-icon-edit" style="margin:0 auto;" />
<f:setPropertyActionListener value="#{guest}" target="#{guestList.selectedGuest}" />
</p:commandButton>
</p:panel>
</p:dataGrid>
<p:dialog header="#{guestList.hasSelected() ? 'Edit Guest' : 'New Guest'}" widgetVar="newGuestDialog" modal="true" showEffect="fade" hideEffect="fade">
<p:outputPanel id="newGuestDetail">
<h:outputText value="'#{guestList.selectedGuest.name}'"/>
<p:inputText id="guestName" value="#{guestList.hasSelected() ? '' : guestList.selectedGuest.name}" pt:placeholder="Name"/>
<p:commandButton value="#{guestList.selectedGuest == null ? 'Create Guest' : 'Update Guest'}"/>
</p:outputPanel>
</p:dialog>
</h:form>
The hasSelected() method evaluates whether the selected guest is null or not, returning true if not null. The selectedGuest should be set when the commandButton is clicked so that an object is available for retrieval by the dialog, however, with tracers in the get/set for selectedGuest, I am not seeing the setter called with the above snippet. If I remove the inputText, then even though the hasSelected is still returning false, and thus the 'New Guest' is heading the dialog, the outputText is filled with a value.
I found this great post talking about the order of execution with respect to the action, action listener, etc., but don't think this quite my issue: Differences between action and actionListener.
So the ultimate question is why will my setter get called with the command button when I only have an outputText, but with an inputText, I never see it called in the log?
I appreciate the time and help anyone can provide.
Even if we fix your problem, this construct
<p:inputText value="#{guestList.hasSelected() ? '' : guestList.selectedGuest.name}">
is not ever going to work. It needs to reference a model property, not an empty string.
You'd best just reuse the edit form and let the create button precreate an empty entity. This would simplify a lot in the view side. It'd be more easy if the entity has an #Id property which is only present when it's persisted in the database.
Here's a kickoff example:
<h:form id="entitiesForm">
<p:dataTable id="entitiesTable" value="#{bean.entities}" var="entity">
<p:column>#{entity.foo}</p:column>
<p:column>#{entity.bar}</p:column>
<p:column>
<p:commandButton id="edit" value="Edit"
process="#this" action="#{bean.edit(entity)}"
update=":entityDialog" oncomplete="PF('entityDialog').show()" />
<p:commandButton id="delete" value="Delete"
process="#this" action="#{bean.delete(entity)}"
update=":entitiesForm:entitiesTable" />
</p:column>
</p:dataTable>
<p:commandButton id="add" value="Add"
process="#this" action="#{bean.add}"
update=":entityDialog" oncomplete="PF('entityDialog').show()" />
</h:form>
<p:dialog id="entityDialog" widgetVar="entityDialog"
header="#{empty bean.entity.id ? 'New' : 'Edit'} entity">
<h:form id="entityForm">
<p:inputText id="foo" value="#{bean.entity.foo}" />
<p:inputText id="bar" value="#{bean.entity.bar}" />
<p:commandButton id="save" value="#{empty bean.entity.id ? 'Create' : 'Update'} entity"
process="#form" action="#{bean.save}"
update=":entitiesForm:entitiesTable" oncomplete="PF('entityDialog').hide()" />
</h:form>
</p:dialog>
With this #ViewScoped bean:
private List<Entity> entities; // +getter
private Entity entity; // +getter
#EJB
private EntityService entityService;
#PostConstruct
public void load() {
entities = entityService.list();
entity = null;
}
public void add() {
entity = new Entity();
}
public void edit(Entity entity) {
this.entity = entity;
}
public void save() {
entityService.save(entity); // if (id==null) em.persist() else em.merge()
load();
}
public void delete(Entity entity) {
entityService.delete(entity); // em.remove(em.find(type, id))
load();
}
See also:
Creating master-detail pages for entities, how to link them and which bean scope to choose
Keep p:dialog open when a validation error occurs after submit
I have some problems with PrimeFaces 5.2 and client components update mechanism
I created a web page with a button that triggers a server side method. This method update a List of objects and finally
a datatable will be updated with new contents of the List.
<h:form>
...
<p:commandButton value="Add parameters" action="#{adminBean.addParams}"
update=":growl :#{tblSensors.clientId}" />
</h:form>
<h:form>
<p:dataTable id="tblSensors"
var="sensorElem" value="#{adminBean.sensors}"
binding="#{tblSensors}"
>
...
</p:dataTable>
</h:form>
Unfortunatelly when the procedure callback is over, my data table are not updated .. Sincerlly I'm not able to find the problem.
There are no exception in debug phase and I saw nothing in Response data from Firebug.
UPDATE: I saw that when the bean method is called and some variable has been changed; this changes aren't persistent and they are missed every time the method is called
UPDATE 2: as requested, I add the bean code:
#ManagedBean(name="adminBean")
#SessionScoped
public class AdminBean implements Serializable{
private List<Sensor> sensors;
public List<Sensor> getSensors() {
return sensors;
}
public void setSensors(List<Sensor> sensors) {
this.sensors = sensors;
}
//...
#PostConstruct
public void init(){
//...
//initialize sensor list
this.sensors = new ArrayList<Sensor>();
//...
}
//method for adding new sensor
public void addParams(){
try{
//add new sensor element to the list
this.sensors.add(new Sensor(this.param_name,Double.parseDouble(this.min_val),Double.parseDouble(this.max_val),
this.unit, this.selectedChartType, this.selectedFieldType, id_counter++));
}catch(Exception e){
System.out.println("Error "+e.getMessage());
System.out.println("stack "+e.getStackTrace());
}
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,"Successful", "New sensor added!"));
}
//...
}
UPDATE 3: fix some namespace errors.
althouh I'm not familiar with dataTables with data bindings, I think the update-statement is not correct, you need to update the datatable when triggering the commandButton
update=":growl, :tblSensors"
Why not just specify the form id so that updating child elements will be more straightforward? try:
<h:form>
...
<p:commandButton value="Add parameters" action="#{amminBean.addParams}"
update=":growl :datatableform:tblSensors" />
</h:form>
<h:form id="datatableform">
<p:dataTable id="tblSensors"
var="sensorElem" value="#{aminBean.sensors}"
binding="#{tblSensors}">
...
</p:dataTable>
</h:form>
I resolve my issue changing the implementation philosophy: I divide the tab contents in 2 separate xhtml files with related beans, the first one for "parent" element management and the second one for its child elements.
so, the first xhtml:
<h:form>
<p:panel id="panel" header="New Station" style="margin-bottom:10px;">
<h:panelGrid columns="2" cellpadding="5">
<p:inputText id="stationName" required="true" value="#{adminBean.stationName}"/>
<p:inputText id="description" required="true" value="#{adminBean.description}" />
<p:outputLabel value="Station type" for="stationType" />
<p:selectOneMenu id="stationType" value="#{adminBean.selectedStationType}" >
<f:selectItem itemLabel="Select Type" itemValue="-1" noSelectionOption="false" />
<f:selectItems value="#{adminBean.stationType}" />
</p:selectOneMenu>
</h:panelGrid>
</p:panel>
<p:commandButton value="Cancel" action="#{adminBean.cancella}" icon="ui-icon-check" />
<p:commandButton value="Next >" id="nextId" binding="#{nextId}" action="#{adminBean.nextStep}"
icon="ui-icon-check" update=":growl" />
</h:form>
when user selects the Next Button, a new page will be called and its bean will use the bean related with first page in order to retrieve all needed info and show its metadata correctly.
this is the second page:
<h:form>
<p:panel id="panel2" header="Aggiungi sensori" style="margin-bottom:10px;">
<h:panelGrid columns="2" cellpadding="5">
<p:inputText id="param_name" required="true" value="#{adminSensorsBean.param_name}"/>
<p:selectOneMenu id="chartType" value="#{adminSensorsBean.selectedChartType}" >
<f:selectItem itemLabel="Select Type" itemValue="-1" noSelectionOption="false" />
<f:selectItem itemLabel="Line" itemValue="LINE" noSelectionOption="false" />
<f:selectItem itemLabel="Bar" itemValue="BAR" noSelectionOption="false" />
</p:selectOneMenu>
//...
<p:selectOneMenu id="fieldType" binding="#{fieldType}" value="#{adminSensorsBean.selectedFieldType}" >
<f:selectItem itemLabel="Select Field" itemValue="-1" noSelectionOption="false" />
<f:selectItems value="#{adminSensorsBean.fieldsType}" />
</p:selectOneMenu>
</h:panelGrid>
</p:panel>
<p:commandButton value="Add Sensor" id="addSensorId" binding="#{addSensorId}"
action="#{adminSensorsBean.addSensor}"
icon="ui-icon-check" update=":growl :#{tblSensors.clientId}" />
</h:form>
<h:form>
<p:dataTable id="tblSensors"
var="sensorElem"
value="#{adminSensorsBean.sensors}"
scrollable="true"
rowKey="#{sensorElem.id}"
binding="#{tblSensors}"
scrollHeight="150"
>
//...
//this table will be filled with data from form above
//...
</p:dataTable>
</h:form>
//...
<h:form>
<p:commandButton value="Submit" id="submitId" binding="#{submitId}" action="#{adminSensorsBean.saveStation}"
icon="ui-icon-check" update=":growl" />
</h:form>
through the Add Sensor button new information will be inserted into the tableView by the called bean method.
#ManagedBean(name="adminSensorsBean")
#SessionScoped
public class AdminSensorsBean implements Serializable{
//Managed property from bean of first page
#ManagedProperty(value="#{adminBean}")
private AdminBean adminBean;
//...
#PostConstruct
public void init(){
//Here all second page elements as FieldType list, will be initialized using stored information from managed property.
}
//...
}
In this way everything works fine! Honestly I don't known why update event didn't work when I putted all my code in only one jsf page..is it a PrimeFaces/JSF bug? maybe but I don't sure.
Thank you for the support, and sorry for my rough english
I have a datatable with custom delete button when I try to send the id of the selected row to the backing bean, but i always get the same value, this is my code:
<p:dataTable id="result" var="service" value="#{bean.services}" editable="true">
<!-- ajax -->
<p:ajax event="rowEdit" listener="#{bean.onEdit}" update=":form:msg" />
<p:ajax event="rowEditCancel" listener="#{bean.onCancel}" update=":form:msg" />
.....
<p:column headerText="delete" style="width:100px;">
<p:confirmDialog id="confirmation" message="are u sure?" header="delete item" widgetVar="confirmation" showEffect="fade" hideEffect="explode">
<p:commandButton value="Yes" onclick="PF('confirmation').hide()" actionListener="#{bean.onDeleteRow}">
<f:setPropertyActionListener target="#{bean.cve}" value="#{service.id.cve}" />
</p:commandButton>
<p:commandButton value="No" onclick="PF('confirmation').hide()" type="button" />
</p:confirmDialog>
<p:commandLink id="deleteLink" onclick="PF('confirmation').show()" styleClass="ui-icon ui-icon-trash"/>
</p:column>
</p:dataTable>
here is the baking bean code:
#ManagedBean
#ViewScoped
#SuppressWarnings("serial")
public class Bean implements Serializable{
private String cve;
...
public void setcve(String cve) {
this.cve = cve;
}
....
public void onDeleteRow(){
try {
System.out.println("delete-->" + this.cve );
} catch (Exception e) {
e.printStackTrace();
}
}
}
In the tag you can see the value that I'm sending as a parameter but I always leave the last value of datatable ...
What am I doing wrong?
Thank you very much for the support
Also there is another problem in your code, you have and Dialog for each row in the datatable, its a bad idea... you should keep the button on the row and set the entity that you want to delete when click at this button and latter just show the dialog, which is just one... something like this: also, change the propertyAcionListener to your delete link
<p:commandLink id="delete_link" oncomplete="deleteDlg.show();">
Delete
<f:setPropertyActionListener value="#{service.id.cve}" target="#{bean.cve}" />
</p:commandLink>
Where is the selection for datatable?
your xhtml
<p:dataTable id="result" var="service" value="#{bean.services}" editable="true">
must be xhtml
<p:dataTable id="result" var="service" value="#{bean.services}" selection="#{bean.selected}" editable="true">
you can find datatable selection example here