I just started learning jsf and I encountered a basic problem. I displayed a list of objects in dataTable and created form for each row to call a function with right parameter:
<h:dataTable value="#{test.getMyItems()}" var="o"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row">
<h:column>
<f:facet name="header">Content</f:facet>
#{o.content}
</h:column>
<h:column>
<h:form>
<h:commandLink action="#{test.edit}" value="edit">
<f:param name="id" value="#{o.id}" />
</h:commandLink>
</h:form>
</h:column>
</h:dataTable>
And now I wanted to redirect user to edit page whit a form which has inputs set to proper values. So in function edit I set values to the variables:
public String edit() {
this.name = "test1";
this.description = "test2";
return "/edit.xhtml?faces-redirect=true";
}
And in edit view I wanted to display them:
<h:form>
<h:outputLabel value="name:" />
<h:inputText value="#{test.name}" />
<h:outputLabel value="description" />
<h:inputText value="#{test.description}" />
<h:commandButton value="Add" action="#{edit.update()}"/>
</h:form>
but inputs are empty. Why?
And Test class:
#ManagedBean (name = "test")
#ViewScoped
public class Test {
private String name;
private String description;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public String edit() {
this.name = "test1";
this.description = "test2";
return "/edit.xhtml?faces-redirect=true";
}
public List<Item> getMyItems() {
List<Item> items = new ArrayList<Item>();
Item i = new Item("1", "g", "f");
items.add(i);
return items;
}
public void update() {
}
They are empty because you're sending a redirect to a new view. A view scoped bean lives as long as the current view lives. A redirect to a new view destroys this.
In this specific construct, you need a <h:link>, not a <h:commandLink>.
Replace
<h:form>
<h:commandLink action="#{test.edit}" value="edit">
<f:param name="id" value="#{o.id}" />
</h:commandLink>
</h:form>
by
<h:link value="edit" outcome="edit">
<f:param name="id" value="#{o.id}" />
</h:link>
with in edit.xhtml
<f:metadata>
<f:viewParam name="id" value="#{edit.id}" />
<f:viewAction action="#{edit.init}" />
</f:metadata>
See also:
Creating master-detail pages for entities, how to link them and which bean scope to choose
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to navigate in JSF? How to make URL reflect current page (and not previous one)
How to choose the right bean scope?
Related
How I can pass params to another view using JSF? Will explain:
All begin in index.xhtml, index use the usuarioController (I called usuarioBean)
<f:metadata>
<f:viewParam name="id" value="#{usuarioBean.usuario.id}" />
<f:viewParam name="nome" value="#{usuarioBean.usuario.nome}" />
</f:metadata>
<h:form>
<h:dataTable value="#{usuarioBean.listarUsuarios()}" var="usuario">
<h:column>
<f:facet name="header">Id</f:facet>
<h:outputText value="#{usuario.id}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">Nome</f:facet>
<h:outputText value="#{usuario.nome}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">Opcoes</f:facet>
<h:link value="Cadastrar Endereco" outcome="endereco?faces-redirect=true" includeViewParams="true" />
</h:column>
</h:dataTable>
</h:form>
My controller is basic:
#ViewScoped
#ManagedBean(name="usuarioBean")
public class UsuarioController implements Serializable {
#Inject
private EntityManager manager;
private Usuario usuario;
public UsuarioController(){
this.usuario = new Usuario();
}
public List<Usuario> listarUsuarios(){
return manager.createNativeQuery("SELECT * FROM usuario", Usuario.class).getResultList();
}
(...)
On click "Cadastrar Endereco" I want call the page endereco.xhtml (it use EnderecoController, called of enderecoBean) and I want get the params id and nome, but I'm having trouble getting these parameters.
In endereco.xhtml, I have:
<f:metadata>
<f:viewParam name="id" value="#{enderecoBean.usuario.id}" />
<f:viewParam name="nome" value="#{enderecoBean.usuario.nome}" />
</f:metadata>
Id: <h:inputText value="#{enderecoBean.usuario.id}" />
<br />
Nome: <h:inputText value="#{enderecoBean.usuario.nome}" />
<br />
And my controller too is basic:
#ViewScoped
#ManagedBean(name="enderecoBean")
public class EnderecoController implements Serializable {
#Inject
private EntityManager manager;
private Endereco endereco;
private Usuario usuario;
public EnderecoController(){
this.endereco = new Endereco();
}
public List<Endereco> listarEnderecos(){
return manager.createNativeQuery("SELECT * FROM usuario", Endereco.class).getResultList();
}
I need recovery this params because I need save enderecos, and enderecos is dependent of usuario.
For more information, my code is here: github.com/eltonsantos/embeddedClasses
I have a p:inputTextarea and I need the value of it while processing the form. It turned out that every time I submit the form I get all the values except the one from the textarea. #{xyzUI.description} is a String object with regular getters and setters.
<ui:composition>
<h:form id="form1">
<p:panel rendered="...">
<p:panel id="formPanel">
<p:panelGrid columns="2" cellpadding="5">
<!-- other form elements -->
<p:outputLabel>Description:</p:outputLabel>
<p:inputTextarea value="#{xyzUI.description}" style="width: 350px;" counter="display" counterTemplate="{0} characters remaining" maxlength="2000" autoResize="true" rows="4" />
<h:panelGroup />
<h:outputText id="display" />
</p:panelGrid>
<p:commandButton rendered="#{not xyzUI.noChange}" action="#{xyzUI.submitForm}" update="formPanel" ajax="true" value="Apply" >
<p:ajax update="formPanel"></p:ajax>
</p:commandButton>
</p:panel>
</p:panel>
</h:form>
<ui:composition>
In my backing bean the value is always "". I don't know what's wrong.
public void submitForm()
{
...
tmp.setDescription(description); // String is always "" while debugging
myList.add(tmp);
RequestContext.getCurrentInstance().update("content");
}
I ran your code locally and discovered the issue. In the command button, remove the p:ajax call.
PrimeFaces command buttons are ajax enabled by default.
So change this:
<p:commandButton rendered="#{not xyzUI.noChange}" action="#{xyzUI.submitForm}" update="formPanel" ajax="true" value="Apply" >
<p:ajax update="formPanel"></p:ajax>
</p:commandButton>
To this:
<p:commandButton rendered="#{not xyzUI.noChange}" action="#{xyzUI.submitForm}" update="formPanel" value="Apply" />
My backing bean for reference
#ManagedBean
#ViewScoped
public class xyzUI implements Serializable{
private static final long serialVersionUID = 6259024062406526022L;
private String description;
private boolean noChange = false;
public xyzUI(){
}
public void submitForm(){
System.out.println(description);
}
public boolean isNoChange() {
return noChange;
}
public void setNoChange(boolean noChange) {
this.noChange = noChange;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
I'm working with JSF technology. I've 2 views and 2 beans. The first View (homepage.xhtml) sets a text parameter in the first Bean (UserBean) which is like so:
#ManagedBean
#SessionScoped
public class UserBean implements Serializable{
private String searchText;
public UserBean(){}
public String search() {
return "searching?faces-redirect=true&text="+searchText;
}
A commandButton in the view submits the search, and calls the UserBean.search().
I have this view in the searching.xhtml, which is a simple DataList component of PrimeFaces showing a list of a user:
<f:metadata>
<f:viewParam name="text" value="#{searchView.searchText}"/>
<f:event type="preRenderView" listener="#{searchView.init()}"></f:event>
</f:metadata>
<h:head>
<title>Search Results</title>
</h:head>
<h:body>
<h:form id="resultsForm">
<p:dataList var="user" value="#{searchView.results}" type="unordered" itemType="none" paginator="true" rows="10" styleClass="paginated">
<f:facet name="header">
Results for #{searchView.searchText}:
</f:facet>
<p:panel>
<p:commandLink update=":resultsForm:userDetail" oncomplete="PF('userDialog').show()" title="user dettagli" styleClass="ui-icon ui-icon-search" style="float:right;margin-right:50px">
<f:setPropertyActionListener value = "#{user}" target="#{searchView.selectedUser}"/>
<h:outputText value="#{user.firstName}, #{user.lastName}" />
</p:commandLink>
<h:outputText value="#{user.firstName} #{user.lastName} (#{user.email})" style="display:inline-block" />
</p:panel>
</p:dataList>
<p:dialog header="User Info" widgetVar="userDialog" modal="true" showEffect="blind" hideEffect="explode" resizable="false">
<p:outputPanel id="userDetail" style="text-align:center;">
<p:panelGrid columns="2" rendered="#{not empty searchView.selectedUser}" columnClasses="label,value">
<h:outputText value="First name:" />
<h:outputText value="#{searchView.selectedUser.firstName}" />
<h:outputText value="Last Name" />
<h:outputText value="#{searchView.selectedUser.lastName}" />
<h:outputText value="Calendar" />
<h:outputText value="#{searchView.selectedUser.visibility}" />
</p:panelGrid>
</p:outputPanel>
</p:dialog>
</h:form>
<br/>
</h:body>
In the end, I've this backing bean:
#ManagedBean
#ViewScoped
public class SearchView implements Serializable {
private List<User> results;
private User selectedUser;
private String searchText;
#EJB
private SearchingManager sm;
public void init() {
System.out.println("print search text:" + searchText);
results = sm.search(searchText);
}
public SearchView() {
}
public void setSelectedUser(User selectedUser) {
System.out.println("setter of selected user");
this.selectedUser = selectedUser;
}
public User getSelectedUser() {
System.out.println("getter of selected user");
return selectedUser;
}
It works and shows the results of the search correctly but when it opens the page of results I notice this output:
Informazioni: print search text: Mario
Informazioni: getter of selected user
So I'm wondering why that getSelectedUser() is called without selecting any user. Moreover when I select a user it shows an empty dialog and this is the outcome:
Informazioni: getter of selected user
Informazioni: getter of selected user
Informazioni: getter of selected user
Informazioni: print search text: Mario
Informazioni: getter of selected user
So it recalls the init() function why?
And the worst thing is that if we close the Dialog and reopen it, the result is something like that but with
Informazioni: print search text: null
and it stops because of NullPointerException.
I'm spending days searching about this setPropertyActionListener but I can't understand this behavior of the system.
I have a JSF 2 form like this:
<h:form>
<h:panelGrid columns="2">
<a4j:repeat value="#{dialog.departments}" var="depart">
<h:inputText value="#{depart.name}"/>
<h:selectOneRadio value="#{depart.hasSubdepartment}">
<f:ajax render="#form" execute="#form" immediate="true"/>
<f:selectItem itemValue="#{true}"/>
<f:selectItem itemValue="#{false}"/>
</h:selectOneRadio>
<a4j:repeat value="#{depart.subdepartments}" var="sub" rendered="#{depart.hasSubdepartment}">
<h:inputText value="#{sub.name}"/>
<h:outputText value=" " />
</a4j:repeat>
</a4j:repeat>
</h:panelGrid>
</h:form>
I have simply the form. As you could see, this form displays data structure of departments like a tree.
What I want to implements is that if user switch the radio button to true, the sub-departments will be displayed, if switch to false, the sub-departments will be hidden.
The problem is that:
If the execute value of the f:ajax tag is set to #form, the validation of the backing beans such as #NotNull and #Size will be called. But we don't want to call the validation now since we do not want to save the data now.
If the execute value of the f:ajax tag is set to #this, it seems that the after the ajax request, the value of the radio reverts. For example, if the radio value is false, and we click true, then after the ajax request, the value go back to false, and the sub-department part is not rendered. This will not happen if execute is set to #form.
Thanks very much if you have any idea or hint.
I don't have a Richfaces integrated testing environment, however I've achieved what you want in plain JSF (that's why it could be an ajax4jsf specific issue). Here you have a test case which works and follows SSCCE standards. Tested with Mojarra 2.1.26 & Tomcat 6:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head />
<h:body>
<h:form>
<h:panelGrid columns="2">
<ui:repeat value="#{dialog.departments}" var="depart">
<h:inputText value="#{depart.name}" />
<h:selectOneRadio value="#{depart.hasSubdepartments}">
<f:ajax render="#form" immediate="true" />
<f:selectItem itemValue="#{true}" />
<f:selectItem itemValue="#{false}" />
</h:selectOneRadio>
<h:panelGroup id="subdepartmentPanel"
rendered="#{depart.hasSubdepartments}">
<ui:repeat value="#{depart.subdepartments}" var="sub">
<h:inputText value="#{sub.name}" />
</ui:repeat>
</h:panelGroup>
</ui:repeat>
</h:panelGrid>
</h:form>
</h:body>
</html>
#ManagedBean
#ViewScoped
public class Dialog {
public class Department {
private String name;
private List<Department> subdepartments = new ArrayList<Dialog.Department>();
private boolean hasSubdepartments;
public Department(String name) {
this.name = name;
}
public String getName() {
return name;
}
public List<Department> getSubdepartments() {
return subdepartments;
}
public boolean isHasSubdepartments() {
return hasSubdepartments;
}
public void setHasSubdepartments(boolean hasSubdepartments) {
this.hasSubdepartments = hasSubdepartments;
}
public void setName(String name) {
this.name = name;
}
public void setSubdepartments(List<Department> subdepartments) {
this.subdepartments = subdepartments;
}
}
private List<Department> departments = new ArrayList<Dialog.Department>();
public Dialog() {
// Create departments and subdepartments
departments.add(new Department("First Department"));
Department d = new Department("Second department");
d.getSubdepartments().add(new Department("Subdepartment"));
departments.add(d);
}
public List<Department> getDepartments() {
return departments;
}
}
I am able to render dynamic but don't know how to get those dynamically created values in back end.
test.xhtml
<h:form>
Insert Your Desire Number : <h:inputText value="#{bean.number}">
<f:ajax listener="#{bean.submitAjax}" execute="#form" render="#form" event="keyup" />
</h:inputText>
<br></br>
<h:outputText value="#{bean.text}" />
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:inputText value="#{item.value}" />
</h:column>
</h:dataTable>
<h:commandButton value="Submit" action="#{item.submit}" />
</h:form>
If I render 3 input boxes, and when I submit the button i get the last value only, Can someone guide me how can i
Bean.java
#ManagedBean(name="bean")
#SessionScoped
public class Bean {
private int number;
private List<Item> items;
private Item item;
//getter and setter are omitted
public void submitAjax(AjaxBehaviorEvent event)
{
items = new ArrayList<Item>();
for (int i = 0; i < number; i++) {
items.add(new Item());
}
}
}
Item.java
private String value;
//getter and setter are omitted
public void submit() {
System.out.println("Form Value : "+value);
}
Your submit() method is in the wrong place. You should put it on the managed bean, not on the entity.
Thus so,
<h:commandButton value="Submit" action="#{bean.submit}" />
with
public void submit() {
for (Item item : items) {
System.out.println(item.getValue());
}
}
or more formally,
#EJB
private ItemService service;
public void submit() {
service.save(items);
}