i have a problem with my primefaces datatable, rows are empty.
<h:body>
<ui:composition template="../shared/commonLayout.xhtml">
<ui:define name="content">
<h:form>
<p:dataTable id="users" var="user" value="#{UserManagedBean.userList}" style="width: 40%">
<p:column>
<f:facet name="header">
<h:outputText value="FirstName" />
</f:facet>
<h:outputText value="#{user.firstname}" />
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>
</h:body>
#ManagedBean(name = "UserManagedBean")
#SessionScoped
public class UserManagedBean {
//..
/**
* Get Users List.
*
* #return List - User List
*/
public final List<User> getUserList() {
userList = new ArrayList<User>();
userList.addAll(getUserService().getItems());
return userList;
}
}
i'm using spring, hibernate, jsf managed beans.
can somebody help me please?
The code you have posted should work if:
getUserList() returns some rows, filled with some data
User class has a field firstname with getter and setter (note the case, n is lowercase in your column)
That firstname field is populated (not empty)
Can you verify the above?
A few things to correct in your code:
Don't do business logic in the getter; move that code into a #PostConstruct
Don't back a page with a #SessionScoped bean; it's a design-smell and almost never ends well. Use the #RequestScoped or #ViewScoped instead.
Everything outside a <ui:composition/> is ignored by the facelets engine. What that means is that all the tags you've defined outside it will have no effect (the <h:body/>) for example
Related Reading:
Why JSF calls getters multiple times
Request parameter is null during postback
Related
The objective is to have a h:commandButton and once I have clicked it, using AJAX it will show the datatable "listaActores" (initially not showing it).
How could i do this? I have search for a solution, but I only found how to re-render the table once is present. My current code shows the table without doing nothing and clicking the button doesn't do anything.
<h:form>
<h:commandButton id="submit" value="Submit">
<f:ajax event="click" execute="#this" render="listaActores" />
</h:commandButton>
<h:dataTable id="listaActores" border="1"
value="#{peliculasEditarBean.listaActores}" var="actor">
<h:column>
<f:facet name="header">NOMBRE</f:facet>
#{actor.nombre}
</h:column>
<h:column>
<f:facet name="header">APELLIDO</f:facet>
#{actor.apellido}
</h:column>
</h:dataTable>
</h:form>
Your question is somewhat incomplete, but I'll answear anyway. Two things:
You're not saying how the table is "initially not showing". If there is some rendered on it, than you need to know that you must render a parent of the table. You can render only things that exist in rendered HTML. See for example this answer.
If you'll put action in the button you'll see that the AJAX won't work. You need to change event to action or delete this attribute to use a default.
I preperend simple working example (BTW. Welcome on Stackoverflow :-) If you want get help faster Minimal, Reproducible Example should be your's part of a question :-)):
(XHTML, added action to commandButton and remove event in f:ajax)
<h:form>
<h:commandButton id="submit" value="Submit"
action="#{peliculasEditarBean.initialize}">
<f:ajax execute="#this" render="listaActores" />
</h:commandButton>
<h:dataTable id="listaActores" border="1"
value="#{peliculasEditarBean.listaActores}" var="actor">
<h:column>
<f:facet name="header">NOMBRE</f:facet>
#{actor.nombre}
</h:column>
<h:column>
<f:facet name="header">APELLIDO</f:facet>
#{actor.apellido}
</h:column>
</h:dataTable>
</h:form>
(and bean)
#ManagedBean
#ViewScoped
public class PeliculasEditarBean implements Serializable {
private List<Actor> listaActores = null;
public List<Actor> getListaActores() {
return listaActores;
}
public void initialize() {
listaActores = new ArrayList<>(3);
listaActores.add(new Actor("foo", "bar"));
listaActores.add(new Actor("foo", "foo"));
listaActores.add(new Actor("bar", "bar"));
}
public class Actor {
private final String nombre;
private final String apellido;
Actor(String nombre, String apellido) {
this.nombre = nombre;
this.apellido = apellido;
}
public String getApellido() {
return apellido;
}
public String getNombre() {
return nombre;
}
}
}
I am seeing different behaviors of and in a page containing multiple forms.
Here is my backing bean:
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class MultiFormBean
{
String inputText1 = "";
String inputText2 = "";
#PostConstruct
public void initializeBean(){
System.out.println("PostConstruct Called ------------------");
}
public String getInputText1()
{
return inputText1;
}
public void setInputText1(String inputText1)
{
this.inputText1 = inputText1;
}
public String getInputText2()
{
return inputText2;
}
public void setInputText2(String inputText2)
{
this.inputText2 = inputText2;
}
public void doSubmit1() {
inputText2 = inputText1;
}
public void doSubmit2() {
inputText1 = inputText2;
}
}
When i use the following xhtml , clicking Submit1 and Submit2 any number of times won't call #PostConstruct more than once:
<h:body>
<h:form id="firstForm" prependId="false">
<h:panelGroup layout="block" id="renderTarget1"/>
<h:inputText id="first_input" value="#{multiFormBean.inputText1}"/>
<h:commandButton id="click1" action="#{multiFormBean.doSubmit1}" value="submit1" type="submit"
onclick="javascript:jsf.ajax.request(this, event, {execute:'firstForm', render:'renderTarget1 secondForm'}); return false;">
</h:commandButton>
</h:form>
<h:form id="secondForm" prependId="false">
<h:panelGroup layout="block" id="renderTarget2"/>
<h:inputText id="second_input" value="#{multiFormBean.inputText2}"/>
<h:commandButton id="click2" action="#{multiFormBean.doSubmit2}" value="submit2" type="submit"
onclick="javascript:jsf.ajax.request(this, event, {execute:'secondForm', render:'renderTarget2 firstForm'}); return false;">
</h:commandButton>
</h:form>
</h:body>
But the following xhtml would call #PostConstruct more than once:
<h:body>
<h:form id="firstForm" prependId="false">
<h:panelGroup layout="block" id="renderTarget1"/>
<h:inputText id="first_input" value="#{multiFormBean.inputText1}"/>
<a4j:commandButton id="click1" action="#{multiFormBean.doSubmit1}" value="submit1" type="submit" execute="#form" render="renderTarget1,secondForm"/>
</h:form>
<h:form id="secondForm" prependId="false">
<h:panelGroup layout="block" id="renderTarget2"/>
<h:inputText id="second_input" value="#{multiFormBean.inputText2}"/>
<a4j:commandButton id="click2" action="#{multiFormBean.doSubmit2}" value="submit2" type="submit" execute="#form" render="renderTarget2,firstForm"/>
</h:form>
</h:body>
Please can anyone help me use the <a4j:commandButton> instead of <h:commandButton>
Also i see that i cannot call the method doSubmit2() with a4j commandButton
I think that problem here is in bug inside JSF2 and Richfaces4. From 4 version Richfaces started using JSF embedded ajax capabilities. And There is a bug with using multiple forms on page with ajax requests. The problem there that richfaces renders special hidden input with the id of currently rendered view state. This id is changed when new view is rendered. And it is also submitted with every request to show that it belongs to some specific view. So when you have multiple forms on the same page after first ajax request the view state is getting the wrong place and it can be not submitted again second time. Sometimes behavior looks like very very wierd with no logical description.
PostConstruct is called twice because server thinks that two requests belong to different views(view state is not sumbitted) and as far as bean is view scoped it is created twice. After clicking aroung ajax can completelly stop working with this because server woukd not recognize the view(probably what you see when you can not click second submit button).
In the first place I recommend you to use latest available version of JSF and Richfaces. This bug (and many more) may be already fixed there.
myBean is in request scope.
<h:form id="indexFormID">
<a4j:outputPanel ajaxRendered="true" layout="block">
<h:inputText id="inputForHD" value="#{myBean.inputParam}"></h:inputText>
<a4j:commandLink value="Submit" action="#{myBean.myMethod}" reRender="renderSuccess" process="indexFormID:inputForHD"></a4j:commandLink>
</a4j:outputPanel>
<h:panelGroup id="renderSuccess">
<h:panelGroup rendered="#{myBean.someBoolean}">
//Some other JSF components go here
</h:panelGroup>
</h:panelGroup>
</h:form>
MyBean class definition:
private String inputParam;
//Getters and setters are there
public String myMethod()
{
log.debug("~ Value of inputParam" +this.getInputParam()); //This is printing null value for inputParam
//when commandLink is clicked
return null;
}
Why my inputParam is not getting set with the input parameters?
Ok I found few issues with your approach:
<h:inputText id="inputForHD" value="#{myBean.inputParam}"></h:inputText>
You are already mapping the inputParam attribute with this bean, why have a new Id "inputForHD"
Use the inputParam itself, if you want to use inputForHD, you can pick the same from request Parameter map like.
String inputForHD = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("indexFormID:inputForHD");
Also as I mentioned previously wrap the output panel inside the and a4j panel e.g.
<h:panelGroup id="renderSuccess">
<h:panelGroup rendered="#{helloWorld.someBoolean}">
//Some other JSF components go here
<h:inputText id="inputForHDasdasd" value="#{helloWorld.inputParam}"></h:inputText>
</h:panelGroup>
</h:panelGroup>
This is working fine, let know if any issues.
Why after selecting an item in this code, the cities component does not get rendered?
<h:form prependId="false">
<h:panelGrid columns="1">
<h:selectOneMenu value="#{enumBeanStatus.selectedRegion}">
<f:selectItems id="selectItem" value="#{enumBean.regions}" var="region" itemLabel="#{region.label}"/>
<f:ajax listener="#{enumBean.loadCities}" render="cities"/>
</h:selectOneMenu>
<h:outputText id="cities" value="#{enumBean.cities}"/>
</h:panelGrid>
</h:form>
It does send a POST with the selected Region, model gets updated correctly, but the <h:outputText> Component is not rendered.
One of the backing beans:
#Named
public class EnumBean {
private List<Region> regions;
private List<City> cities;
#Inject
EnumBeanStatus enumBeanStatus; //This one is CDI #ApplicationScoped & #Named
// Code...
public void loadCities(){
setCities(City.getCitiesByRegion(enumBeanStatus.getSelectedRegion()));
}
// Getters and Setters
}
Remove prependId="false" from the <h:form>. It prevents <f:ajax> from resolving the right component based on a relative client ID.
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
UIForm with prependId="false" breaks <f:ajax render>
I've been using JSF for a while but there's something that has always confused me. Hopefully someone can help.
Simple example, there's a page that shows a table of "Person"s and when you click on the "Person" name, it takes you to a page to view the details of the "Person".
Typically, I implement a personSearch.jsf page like this:
<h:dataTable value="#{personHandler.persons}" var="person">
<h:column>
<h:commandLink action="#{personHandler.show( person.id )}" >
<h:outputText value="#{person.name}" />
</h:commandLink>
</h:column>
</h:dataTable>
And I implement a personView.jsf page like this:
<h:panelGrid columns="2">
<h:outputText value="Person ID:" />
<h:outputText value="#{personHandler.selectedPerson.id}" />
<h:outputText value="Person Name:" />
<h:outputText value="#{personHandler.selectedPerson.name}" />
</h:panelGrid>
PersonHandler.show(Integer personId) sets personHandler.selectedPerson and then redirects to the personView page.
This all works fine when PersonHandler is a session bean. But I prefer it to be a request scoped bean because the user may have several windows open and I don't want there to be only one selected person per session.
So my question is, what's the "correct" way to do this JSF? I was once able to get what I wanted using a4j:keepAlive on the personHandler, but that always felt like a kludge. Again, this is something I've never understood about JSF.
Any help is greatly appreciated!
rob
If the view is supposed to be bookmarkable, pass the person ID as a GET request parameter instead of a POST request "parameter".
<h:outputLink value="viewperson.xhtml">
<f:param name="id" value="#{person.id}" />
</h:outputLink>
This way you can use two #RequestScoped beans, one for the list and one for the view. You can preload the selected person as follows:
#ManagedProperty(value="#{param.id}")
private Long id;
#PostConstruct
public void init() {
selectedPerson = personDAO.find(id);
}
If it is not supposed to be bookmarkable, then just create a single view which renders the view state conditionally.
<ui:fragment rendered="#{!personHandler.viewMode}">
<h:form>
<h:dataTable value="#{personHandler.persons}" var="person">
<h:column>
<h:commandLink value="#{person.name}" action="#{personHandler.show(person)}" />
</h:column>
</h:dataTable>
</h:form>
</ui:fragment>
<ui:fragment rendered="#{personHandler.viewMode}">
<h:form>
...
<h:commandLink value="Go back" action="#{personHandler.back}" />
</h:form>
</ui:fragment>
(You can if necessary split out the content of the both framgents to another Facelet files which you include by <ui:include>)
This way you can use a single #ViewScoped bean with action methods returning void or null.
public void show(Person selectedPerson) {
this.selectedPerson = selectedPerson;
}
public void back() {
selectedPerson = null;
}
public boolean isViewMode() {
return selectedPerson != null;
}
You can even wrap the whole view in some
<h:panelGroup id="container">
and nest the following in both command links to let Ajax magic do the work
<f:ajax execute="#form" render=":container" />