I have been looking at Primefaces 3.4.2 since IceFaces 3.2.0 has too many issues. I have a dataGrid of vehicles which are contained in a panel. I have an add button and each vehicle panel contains a remove button.
The add works fine; it adds a new vehicle panel each time. The issue is when I delete a vehicle, the panel is removed, but the value(s) remain. For instance, if I have 3 vehicles with the year as 2008, 2010, 2012, and then I delete the first vehicle, you'd think you would see 2 panels remaining with the year as 2010, and 2012. Instead, I see 2008 and 2012. The backing bean is doing it correctly and I do see the correct values if I manually refresh the screen. Now that I have presented my case here's the code:
<p:dataGrid id="vehicleGrid" var="currentVehicle" value="#{vehicleInfoBean.getVehicleList()}" columns="#{vehicleInfoBean.getVehicleList().size()}" styleClass="vehicleInfoPanel" rowIndexVar="rowIdx">
<p:panel header="VEHICLE ##{rowIdx+1}:" style="width:100%" styleClass="textEntryInputTable">
<h:panelGrid columns="1" style="width:100%" styleClass="vehicleInfoPanel">
<ui:include src="../components/vehicleinfo/vehiclecomponents.xhtml">
<ui:param name="currentVehicle" value="#{currentVehicle}" />
<ui:param name="labelOnly" value="false" />
</ui:include>
<div class="deleteButton">
<p:commandButton value="Remove" label="Delete Vehicle" action="#{vehicleInfoBean.deleteVehicle}" update=":vehicleInfoForm:vehicleGrid" process="#this">
<f:setPropertyActionListener value="#{currentVehicle}" target="#{vehicleInfoBean.currentVehicle}" />
</p:commandButton>
</div>
</h:panelGrid>
</p:panel>
</p:dataGrid>
Any ideas? I have tried all sorts of update values including #form, but it's all the same. I haven't used a dataGrid before but I need the iterative capabilities that ice:panelSeries has.
UPDATE: Here's the code in the include:
<h:panelGrid columns="2">
<p:inputText id="vinInput" styleClass="stdFieldControl" value="#{currentVehicle.vin}" label=""
required="true" requiredMessage="VIN is required" >
<p:ajax update="#this vinMsg"/>
</p:inputText>
<p:message id="vinMsg" for="vinInput" errorClass="ui-state-error-text"/>
<p:outputLabel value="-----OR-----"/>
</h:panelGrid>
1/14/2013 - Updated code
<p:dataGrid id="vehicleGrid" var="currentVehicle" value="#{vehicleInfoBean.getVehicleList()}" columns="#{vehicleInfoBean.getVehicleList().size()}" styleClass="vehicleInfoPanel" rowIndexVar="rowIdx">
<p:panel header="VEHICLE ##{rowIdx+1}:" style="width:100%" styleClass="textEntryInputTable">
<h:panelGrid columns="1" style="width:100%" styleClass="vehicleInfoPanel">
<p:inputText id="vinInput" styleClass="stdFieldControl" value="#{currentVehicle.vin}" label="" required="#{empty param['vehicleGrid:0:btnDelete'] and empty param['btnAdd']}" requiredMessage="VIN is required" >
</p:inputText>
<p:message id="vinMsg" for="vinInput" errorClass="ui-state-error-text"/>
<p:outputLabel value="-----OR-----"/>
<h:inputText id="yearInput" styleClass="stdFieldControl" value="#{currentVehicle.year}" label=""
required="#{empty param['vehicleGrid:0:btnDelete']}" requiredMessage="Year is required">
</h:inputText>
<p:message id="yearMsg" for="yearInput"
errorClass="ui-state-error-text"/>
<div class="deleteButton">
<p:commandButton id="btnDelete" value="Remove" label="Delete Vehicle" action="#{vehicleInfoBean.deleteVehicle}" update="#form">
<f:setPropertyActionListener value="#{currentVehicle}" target="#{vehicleInfoBean.currentVehicle}" />
</p:commandButton>
</div>
</h:panelGrid>
</p:panel>
</p:dataGrid>
The add code looks like this:
<div class="addButton" style="padding-left: 2.17%; float: left; clear: both">
<p:commandButton id="btnAdd" value="AddVehicle" label="Add Vehicle" actionListener="#{vehicleInfoBean.addVehicle}" update="vehicleGrid"/>
</div>
Instead of putting the check on the buttons, I decided to set the required attribute of the components referring to the buttons. This code works if I hardcode the iterator index. For example, required="#{empty param['vehicleGrid:0:btnDelete']}". This code points to the first delete button in the panelGrid. What I need is to dynamically derive the index to this - required="#{empty param['vehicleGrid:#{rowIdx}:btnDelete']}". The add button was easy since it doesn't reside in an iterator. How do I code the param in a way that I can dynically refer to the rowId of the panelGrid? The RowId looks confusing but this is coded in a way that each Vehicle Panel is displayed next to the previous panel. The row in this case can be thought of as a column. Anyone have any ideas?
Related
I'm much newbie to the JSF. I am creating a simple crud app. I have done adding, and deleting but there is some problem with updating data..... when edit is clicked, bean is populated with values of whom i want to update. but it is not shown in the next page, in which it is to be edited......
this is the link which leads to editPage
<h:column>
<f:facet name="header">Edit</f:facet>
<h:form>
<h:commandLink value="Edit" action="#{personManipulate.editPerson(person)}"/>
</h:form>
</h:column>
this is the code which assign person data to person entity
public String editPerson(PersonEntity person){
this.person=person;
return "success2";
}
This is the code which updates per save person
public String savePerson(){
if(person.getPersonId() > 0){
personDao.updatePerson(person);
return "success";
}else{
personDao.addPerson(person);
return "success";
}
}
}
This is the page where values should be shown and Updated
<h:form>
<h:panelGrid columns="2">
<f:facet name="header">Person</f:facet>
<h:outputLabel for="firstName" value="First name" />
<h:inputText id="firstName" value="#{personManipulate.person.firstName}"
label="First name" />
<h:outputLabel for="lastName" value="Last name" />
<h:inputText id="lastName" value="#{personManipulate.person.lastName}"
label="Last name" />
<h:outputLabel for="address" value="Address" />
<h:inputText id="address" value="#{personManipulate.person.address}"
label="Address" />
<h:outputLabel for="phone" value="Contact Number" />
<h:inputText id="phone" value="#{personManipulate.person.phone}" />
<h:commandButton action="#{personManipulate.savePerson}" value="Submit" />
<h:button outcome="ShowPersons.xhtml" value="Cancel" />
</h:panelGrid>
</h:form>
This is the navigation rule
<navigation-rule>
<from-view-id>JSF/personManipulate.xhtml</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>JSF/ShowPersons.xhtml</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>JSF/ShowPersons.xhtml</from-view-id>
<navigation-case>
<from-outcome>success2</from-outcome>
<to-view-id>JSF/personManipulate.xhtml</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
On Debugging everything is fine i.e. data is assigned to person object but not shown on update page
Well, you're trying to access the #{personManipulate} bean, which still has not been created when you're in the people list. Supposing it is a #ViewScoped bean as it should, that should be created when you address to JSF/personManipulate.xhtml specifically. So I would encourage you to do the People List -> Edit Person transition using a GET request, instead:
showPersons.xhtml
<h:column>
<f:facet name="header">Edit</f:facet>
<h:form>
<h:link value="Edit" outcome="personManipulate.xhtml">
<f:param name="idPerson" value="#{person.id}" />
</h:link>
</h:form>
</h:column>
That will direct you to an url similar as: personManipulate.xhtml?idPerson=1. Then, load the person before the #{personManipulate} bean makes the rendering task:
personManipulate.xhtml
<f:metadata>
<f:viewParam name="idPerson" value="#{personManipulate.idPerson}" />
<f:event listener="#{personManipulate.loadData}" type="preRenderView" />
</f:metadata>
PersonManipulate.java
public void loadData(ComponentSystemEvent event){
person = service.getPersonById(idPerson);
}
That way you keep both view beans unbound and you use urls for navigation. If you aren't interested in showing the person id in the url, then you can use the Flash scope to pass it from bean to bean. Have a look at the linked posts.
See also:
View parameter when navigating to another page
Understand Flash Scope in JSF2
I have a datatable created in PrimeFaces which receives and render a list of objects. At the end of the row I have a commandButton element and when it is used it do some stuff on the managedBean on the server.
All the data about the current row is retrieved using an object id placed in the command button in the param attribute.
The problem is that I have a selectOneMenu element and it is not related to the object. I select one value that affects the logic behind.
Here is the table:
<h:panelGrid id="panel" columns="2" bgcolor="#cce4ff"
cellpadding="10" cellspacing="1" rendered="#{indexBean.showChannelList}"
style="margin-top: 10px; margin-left: 100px;">
<p:dataTable var="program" value="#{indexBean.programList}" style="width:1000px;"
paginator="True" rows="10" rowIndexVar="row" sortBy="#{program.id}"
paginatorPosition="bottom" widgetVar="programDT" id="programDT">
... That the select
<p:column headerText="text" width="15%">
<h:selectOneMenu id="select-valability" value="#{indexBean.valabilitySelected}" disabled="#{indexBean.disabled}" style="font-size: small;">
<f:selectItems value="#{indexBean.listValabilities}" />
<f:param value="#{program.id}" />
<f:ajax resetValues="true" />
</h:selectOneMenu>
</p:column>
... and there is the command button
<p:column headerText="text" width="20%" style="text-align: center;">
<h:commandButton id="cmd-button-id" value="gen JSON" action="#{indexBean.action}"
style="width: 200px; height: 30px;"
class="ui-button ui-widget ui-state-default ui-corner-all"
>
<f:param name="programId" value="#{program.id}" />
</h:commandButton>
</p:column>
I want to be able to get the value of the select element from that specific row from which the action was triggered.
I've try with context.findComponent() but it gives me null even if I put the absolute path to the element with the index generated by JSF table as form:table:index:staticIdOfSelect.
I don't know how to get the sibling element. That was another though.
From the bean class:
#ManagedBean
#SessionScoped
public class IndexBean
I'm really stuck here.
Thanks in advance!
Use some element on the row to set an ajax listener in the bean to store the data and then update="the element" you want to get the information from.
Based on this subject, I would like to update a <p:overlayPanel> from a datatable to a composite component
View
<h:form id="myForm">
<p:dataTable id="myTable" ...>
<p:column headerText="1">
<p:commandLink id="link"
actionListener="#{bean.update}"
update=":toto" value="Val" />
<p:overlayPanel id="panel" for="link">
<my:view id="toto">
</p:overlayPanel>
</p:column>
</p:dataTable>
</h:form>
Composite
<composite:implementation>
<span id="#{cc.clientId}">
<p:dataTable id="toto" ...>
</p:dataTable>
</span>
</composite:implementation>
However I always get an error message saying that :toto component id can not be reached.
So, how can I access the dataTable placed in the composite ?
EDIT : Actually I changed my mind concerning the utilisation of p:overlayPanel for a p:datatable because of the creation of dynamic ids. I replaced this by a p:dialog and it works great.
I want to write a code in this way, that If I click on a button a data table appears populated with data. before that there should not be the data table in view.
<p:commandButton value="Go" styleClass="apply_button" actionListener="#{searchBean.getUserList}">
<f:attribute name="trigram" value="#{searchBean.trigram}"/>
<f:attribute name="firstName" value="#{searchBean.firstName}"/>
<f:attribute name="lastName" value="#{searchBean.lastName}"/>
</p:commandButton>
here the method getUserList() returns a list of data that should be populated in the data table.and it works.
<p:dataTable value="#{searchBean.listUser}" var="user">
<p:column headerText="Trigram">
<h:outputText value="#{searchBean.trigram}"/>
</p:column>
</p:dataTable>
It shows in the Data Table after I click on the button, But the Data Table appears before the button click with empty fields. How can I modify my codes to show make the Data Table appear after my button click?
Codes are within the <h:form> Tag.
And the Managed Bean searchBean is in #ViewScoped.
You can initialize a simple getter/setter :
private boolean visible = false; // getter/setter
public void getUserList(ActionEvent event)
{
setVisible(true);
// Your code
}
And modify your view like this :
<p:commandButton value="Go" styleClass="apply_button" actionListener="#{searchBean.getUserList}" update="table-wrapper">
<f:attribute name="trigram" value="#{searchBean.trigram}"/>
<f:attribute name="firstName" value="#{searchBean.firstName}"/>
<f:attribute name="lastName" value="#{searchBean.lastName}"/>
</p:commandButton>
<h:panelGroup id="table-wrapper">
<p:dataTable rendered="#{searchBean.visible}" value="#{searchBean.listUser}" var="user">
<p:column headerText="Trigram">
<h:outputText value="#{searchBean.trigram}"/>
</p:column>
</p:dataTable>
</h:panelGroup>
Note the update attribute on button, h:panelGroup wrapper and rendered attribute on table.
I have programmed a little application in which you can register and edit your data. For the authenticity I used a bean class called Authenticity. This class contains an object of Customer (which is a database entity) and methods to login and to logout.
Now I´ve created a page for editing the user: A form with many inputTexts which have the value of authenticity.curUser./(properties). It look like this:
<h:form>
<h:panelGrid columns="2" cellpadding="4px" width="600">
<h:outputText value="firstname:" />
<h:inputText value="#{authenticity.curUser.firstname}"/>
<h:outputText value="lastname:"/>
<h:inputText value="#{authenticity.curUser.lastname}" />
<h:outputText value="street:"/>
<h:inputText value="#{authenticity.curUser.street}" />
<h:outputText value="housebumber"/>
<h:inputText value="#{authenticity.curUser.housenumber}" />
<h:outputText value="Zip:"/>
<h:inputText value="#{authenticity.curUser.zip}" />
<h:outputText value="City:"/>
<h:inputText value="#{authenticity.curUser.city}" />
<h:outputText value="Land"/>
<h:inputText value="#{authenticity.curUser.country}" />
<h:outputText value="email:"/>
<h:inputText value="#{authenticity.curUser.email}" />
<h:outputText value="password:"/>
<h:inputSecret value="#{authenticity.curUser.password}" />
<h:commandButton action="#{authenticity.editUser}" value="Edit" />
</h:panelGrid>
</h:form>
My question now is whether there are better solutions for this problem. Should a AuthenticityBean be actually able to edit the user? Or should I create a extra bean?
I would use a completely separate view scoped bean which holds a brand new copy of the entity representing the logged-in user. Only when the form is successfully edited and saved, then the currently logged-in user can be replaced (the form bean can just access it as a #ManagedProperty).
If you were reusing the same entity in the form; imagine that you're ajax-updating some fields and then cancels/closes the form. The currently logged-in user would then still have the "Wrong" field values in the remnant of the session. This is not correct.