I've got a list of orders on a database, and I want to show two separate datatables in two JSF pages: one table regarding all orders, and one table regarding the current logged user.
Problem is, only the first one is actually showed on the page.
JSF page with the datatable links
<h:commandLink action="#{ordineController.listaOrdini}"
value="Consulta gli ordini esistenti" rendered="#{not empty loginAdmin.admin.email}"/>
<div>
<h:commandLink
action="#{ordineController.listaOrdiniCliente}"
value="Controlla i tuoi ordini"
rendered="#{not empty loginCliente.clienteLoggato.email}">
<f:setPropertyActionListener target="#{ordineController.clienteCorrente}"
value="#{loginCliente.clienteLoggato}" />
</h:commandLink>
</div>
ViewScoped bean
#ManagedBean(name="ordineController")
#ViewScoped
public class OrdineController implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#PostConstruct
public void init() {
ordini = oFacade.getListaOrdini();
listaOrdiniCliente();
}
public String listaOrdini() {
this.ordini = oFacade.getListaOrdini();
return "showOrdini";
}
public String listaOrdiniCliente() {
this.ordiniCliente = oFacade.getOrdiniCliente(clienteCorrente);
return "showOrdiniCliente";
}
/*Getters and setters*
The JSF page that doesn't work (showOrdiniCliente.xhtml)
<h:outputText value="Non c'è nessun ordine."
rendered="#{empty ordineController.ordiniCliente}" />
<h:dataTable id="lista" value="#{ordineController.ordiniCliente}"
var="ordine" rendered="#{not empty ordineController.ordiniCliente}">
The JSF page that does work (showOrdini.xhtml)
<h:outputText value="Non c'è nessun ordine."
rendered="#{empty ordineController.ordini}" />
<h:form rendered="#{not empty ordineController.ordini}">
<h:dataTable id="lista" value="#{ordineController.ordini}"
var="ordine">
Why is the #{ordineController.ordiniCliente} empty?
Shouldn't it be builded along with the "ordini" variable in the #PostConstruct?
edit
Facade method (it retrieves all the orders of a customer)
public List<Ordine> getOrdiniCliente (Cliente cliente) {
try {
TypedQuery<Ordine> q = em.createQuery("SELECT ord FROM Ordine ord WHERE ord.cliente = :cliente", Ordine.class);
q.setParameter("cliente", cliente);
return q.getResultList();
}
catch (Exception e) {
String q = "Il cliente " +cliente.getNickname()+ " non ha creato degli ordini";
System.out.println(q);
return null;
}
}
Related
i am looking for a plain-jsf-solution to handle bookmarkable, parameterbased datatable-pagination.
actually i am using an ajax-approach and a cookie to store the active page. when the user hits F5 or clicks a link in a datatable-row and then returns with "browser-back", i check the cookie to show the last active page.
<h:commandLink value="Next Page">
<f:ajax listener="#{bean.nextPage}" render="dataTable"/>
</h:commandLink>
#ViewScoped
public class PagerBean {
public void nextPage() {
this.resultList = Products.getNextProducts(getFirstResult(),getMaxResult());
addCookie("activePage", getActivePage());
}
}
#ViewScoped
public class ProductBean {
#ManagedProperty(value="#{pager}")
protected PagerBean pager;
#Postconstruct
public void init() {
if (isCookie("activePage"){
pager.setActivePage(getCookie("activePage"));
}
}
}
however, i am looking for a bookmarkable solution, so that we can produce links with specific url-parameters, which are also trackable by browser back/forward-button.
http://foo.com/products?page=1
http://foo.com/products?page=2
http://foo.com/products?page=3
<h:link outcome="/pages/markets/products">
<f:param name="page" value="#{bean.pager.activePage}"/>
</h:link>
#ViewScoped
public class ProductBean {
#ManagedProperty(value="#{pager}")
protected PagerBean pager;
#Postconstruct
public void init() {
final String page = Faces.getRequestParameter("page");
if (null != page){
//load next entries
}
}
}
my only problem is, that with this version, the ViewScoped ProductBean gets newly created on every pagination-action. i think, as the view is not changing, the bean should not be re-created. what is the right approach to get lucky?
found a non-primefaces-solution using h:commandLink and HTML5 History API.
on every pagination-action the current pagenumber is stored in the history. when user navigates, the pagenumber will be restored from history and ajax-submitted again.
<h:commandLink value="Next Page">
<f:ajax listener="#{bean.nextPage}" render="dataTable" onevent="pushState"/>
</h:commandLink>
<h:inputText id="current" value="#{bean.pager.activePage}"/>
<h:commandLink value="Previous Page">
<f:ajax listener="#{bean.prevPage}" render="dataTable" onevent="pushState"/>
</h:commandLink>
<!--hidden action fired when user navigates in history-->
<h:commandLink styleClass="hidden" id="hiddenLink">
<f:ajax execute="current" listener="#{bean.jumpToPage}" render="dataTable" />
</h:commandLink>
JS:
$(window).on('popstate', function(event) {
var pageInHistory = event.originalEvent.state;
if (null == pageInHistory){
pageInHistory = 1;
}
//set page number from history
$('#current').val(pageInHistory);
//trigger ajax-submit
$('#hiddenLink').trigger('click');
});
pushState = function (data){
switch (data.status) {
case "success": {
var currentPage = $('#current').val();
history.pushState(currentPage, null, "?page=" + currentPage);
}
}
Bean
#ViewScoped
public class PagerBean {
private int activePage;
public void jumpToPage() {
//load data for activePage
}
//...
}
I am using RichFaces's ordering list to display a table custom Command objects to the user. The user uses a form to create new commands which are then added to the list. Here is the orderingList implementation:
app.xhtml
<rich:orderingList id="oList" value="#{commandBean.newBatch}" var="com"
listHeight="300" listWidth="350" converter="commandConverter">
<f:facet name="header">
<h:outputText value="New Batch Details" />
</f:facet>
<rich:column width="180">
<f:facet name="header">
<h:outputText value="Command Type" />
</f:facet>
<h:outputText value="#{com.commandType}"></h:outputText>
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="Parameters" />
</f:facet>
<h:outputText value="#{com.parameters}"></h:outputText>
</rich:column>
<rich:column>
<h:commandButton value="Remove #{com.id} : #{com.seqNo}"
action="#{commandBean.remove(com.id,com.seqNo)}"
onclick="alert('id:#{com.id} seqNo:#{com.seqNo}');"/>
</rich:column>
My troubles began when I tried to implement a remove button which would send a command's ID and seqNo to the backing bean (cb) to be removed from the list. Here is the backing bean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class CommandBean implements Serializable{
private static final long serialVersionUID = 1L;
private CommandType type;
private String parameters;
private List<Command> newBatch = new ArrayList<Command>();
private Set<Command> commandSet = new HashSet<Command>();
private String msg = "not removed";
public CommandType[] getCommandTypes() {
return CommandType.values();
}
public void addCommand(CommandType type, String parameters) {
newBatch.add(new Command(type, parameters));
}
CommandType getType() {
return type;
}
void setType(CommandType type) {
this.type = type;
}
String getParameters() {
return parameters;
}
void setParameters(String parameters) {
this.parameters = parameters;
}
public List<Command> getNewBatch() {
return newBatch;
}
public void setNewBatch(List<Command> newBatch) {
this.newBatch = newBatch;
}
public Set<Command> getCommandSet() {
return commandSet;
}
public void setCommandSet(Set<Command> commandSet) {
this.commandSet = commandSet;
}
String getMsg() {
return msg;
}
public void remove(Integer id, Integer seqNo) {
for(Command c : newBatch) {
if(c.getId() == id && c.getSeqNo() == seqNo) {
newBatch.remove(c);
msg = "removed " + c;
return;
}
}
msg = String.format("%d : %d", id,seqNo);
}
}
When the Command (com)'s id and seqNo are passed via #{cb.remove(com.id,com.seqNo)} they are both 0. I also read somewhere that null values are transformed to 0's, so that would explain it. I also tried to pass the Command object directly via #{cb.remove(com)} but the Command was null when bean tried to process it.
I'm betting there is something off with the scoping, but I am too new to JSF to figure it out...
UPDATE
I have eliminated the conflicting #Named tag and have updated the html to reflect the new name of the bean, namely commandBean. Still having issues though.
you can pass the two values as request parameters:
<h:commandButton ... >
<f:param name="id" value="#{com.id}"/>
<f:param name="seqNo" value="#{com.seqNo}"/>
</h:commandButton>
and get retrieve them in managed bean like this:
HttpServletRequest request = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest());
System.out.println(request.getParameter("id"));
System.out.println(request.getParameter("seqNo"));
You're trying to get a value from a variable that is used in a for-cycle after the cycle is over. The #action is being resolved on the server side, by the time the #var is null.
You can do this:
<a4j:commandButton action="#{commandBean.remove()}" … >
<a4j:param assignTo="#{commandBean.idToRemove}" value="#{com.id}"/>
</a4j:commandButton>
The a4j:param resolves the value on client side, when the button is clicked it sends it to the server.
I am having a problem with the SelectOneMenu control. I want the the selected item to be be displayed via the valueChange Ajax event listen. But this is not happening.
However, when I change the value in the SelectOneMenu and then click on the Submit button, then selected value is getting displayed via the 'save' bean function
Cannot figure out why this is not working. Would appreciate any help on this.
Thanks.
The relevant xhtml code is as follows:
<h:form>
<h:dataTable value="#{dynamicList.myData}" var="item" >
<h:column>
<h:outputText value="#{item.oracleType}"></h:outputText>
</h:column>
<h:column>
<h:selectOneMenu value="#{item.coffeeFlavour}" rendered="#{item.showLov}" >
<f:selectItems value="#{item.coffeeList}"></f:selectItems>
<f:ajax event="valueChange" listener="#{dynamicList.listen}" ></f:ajax>
</h:selectOneMenu>
<h:inputText value="#{item.coffeeFlavour}" rendered="#{item.showText}">
</h:inputText>
</h:column>
</h:dataTable>
<p:commandButton value="Submit" action="#{dynamicList.save}" ></p:commandButton>
</h:form>
The relevant bean code is as follows:
#ManagedBean
#ViewScoped
public class DynamicList implements Serializable{
private List<OraclePrfl> oracleList=new ArrayList<OraclePrfl>();
private String coffee;
private Map<String,String> coffeeList=new LinkedHashMap<String,String>();
public List<OraclePrfl> getOracleList() {
return oracleList;
}
public List<OraclePrfl> getMyData()
{
oracleList.clear();
oracleList.add(new OraclePrfl("Oracle Lot Number",new HashMap<String,String>(){
{
put("Coffee2 - Cream Latte", "Cream Latte");
put("Coffee2 - Extreme Mocha", "Extreme Mocha");
put("Coffee2 - Buena Vista", "Buena Vista");
}
},true,false));
oracleList.add(new OraclePrfl("Oracle Product Number",new HashMap<String,String>(){
{
put("ABC", "abc");put("PQR", "pqr");put("XYZ", "xyz");
}
},true,false));
oracleList.add(new OraclePrfl("Oracle Specification",new HashMap<String,String>(){
{
put("MNP", "mnp");put("WXY", "wxy");put("XYZ", "xyz");
}
},true,false));
oracleList.add(new OraclePrfl("Address",false,true));
return oracleList;
}
public void setOracleList(List<OraclePrfl> oracleList) {
this.oracleList = oracleList;
}
public String getCoffee() {
return coffee;
}
public void setCoffee(String coffee) {
this.coffee = coffee;
}
public Map<String,String> getCoffeeList() {
coffeeList.clear();
coffeeList.put("Coffee2 - Cream Latte", "Cream Latte"); //label, value
coffeeList.put("Coffee2 - Extreme Mocha", "Extreme Mocha");
coffeeList.put("Coffee2 - Buena Vista", "Buena Vista");
return coffeeList;
}
public void setCoffeeList(Map<String,String> coffeeList) {
this.coffeeList = coffeeList;
}
public void save(){
for(OraclePrfl oracle:oracleList){
System.out.println("oracle type------"+oracle.getOracleType()+"------coffee----
"+oracle.getCoffeeFlavour());
}
}
public void listen(AjaxBehaviorEvent event){
System.out.println("calling listener "+event.getSource().toString());
for(OraclePrfl oracle:oracleList){
System.out.println("type....."+oracle.getOracleType()+"----value-----
"+oracle.getCoffeeFlavour());
}
}
}
Try removing the event:
<f:ajax listener="#{dynamicList.listen}" ></f:ajax>
It should default to event="change".
I'm trying to implement a list of users names which can be rearranged by clicking on UP or DOWN links.
<ul>
<ui:repeat var="user" value="#{cc.attrs.value}">
<li>
#{user.name}
<h:link outcome = "user" value = "left" onclick="#{accountController.moveDown}">
<f:param name="id" value = "${user.id}" />
</h:link>
</li>
</ui:repeat>
</ul>
The problem here is that it seems that I'm not using the onclick attribute correctly. What is the proper way for doing this?
Edit: Following your advices I placed all the links in a form:
<h:form>
<ui:repeat value="#{cc.attrs.value}" var = "user">
<div class = "user">
<h:commandLink id = "Link1" value = "Up" binding = "#{accountController.ommandLink}" action = "#{accountController.moveUserUp}">
<f:attribute name = "userId" value = "#{user.id}" />
</h:commandLink>
<h:commandLink id = "Link2" value = "Down" binding = "#{accountController.commandLink}" action = "#{accountController.moveUserDown}">
<f:attribute name = "userId" value = "#{user.id}" />
</h:commandLink>
<h:commandLink id = "Link3" value = "Delete" binding = "#{accountController.commandLink}" action = "#{accountController.deleteUser}">
<f:attribute name = "userId" value = "#{user.id}" />
</h:commandLink>
</div>
</h:form>
the Managed Bean:
private UIComponent commandLink;
public void moveUserUp(){
Integer userId = (Integer)commandLink.getAttributes().get("userId");
System.out.println("MOVE TAB LEFT :" + userId);
}
public void moveUserDown(){
Integer userId = (Integer)commandLink.getAttributes().get("userId");
System.out.println("MOVE TAB RIGHT: " + userId);
}
public void deleteUser(){
Integer userId = (Integer)commandLink.getAttributes().get("userId");
System.out.println("DELETE TAB: " + userId);
}
public UIComponent getCommandLink() {
return commandLink;
}
public void setCommandLink(UIComponent commandLink) {
this.commandLink = commandLink;
}
The communication between the command Link and the managed bean is working but in the UI only the last commandLink (close action) is displayed.
In order to invoke a bean action method on click of a link, you need <h:commandLink>. This must be enclosed in a <h:form>.
<h:form>
<h:commandLink ... action="#{bean.action}" />
</h:form>
public String action() {
// ...
return "/other.xhtml";
}
In JSF, only the attributes which interpret the EL expression as a MethodExpression can be used to declare action methods. All other attributes are interpreted as ValueExpression and they are immediately executed when the HTML output is generated by JSF. This covers the onclick attribute, whose value should actually represent a JavaScript function.
In case you actually want to use a GET link, then move the action method to a <f:viewAction> in the target page. This will be invoked on page load of the target page.
<h:link ... outcome="/other.xhtml" />
<f:metadata>
<f:viewAction action="#{bean.onload}" />
</f:metadata>
public void onload() {
// ...
}
See also:
When should I use h:outputLink instead of h:commandLink?
How to send form input values and invoke a method in JSF bean
How do I process GET query string URL parameters in backing bean on page load?
How to navigate in JSF? How to make URL reflect current page (and not previous one)
Following your advices I placed all the links in a form
The communication between the command Link and the managed bean is working but in the UI only the last commandLink (close action) is displayed.
You should not bind multiple physically different components to one and same bean property. Also the <f:attribute> to pass arguments is hacky and not necessary anymore in JSF2. Assuming that you're using a Servlet 3.0 / EL 2.2 container (your question history confirms that you're using Glassfish 3), rather just pass the argument as method argument directly:
<h:commandLink id="Link1" value="Up" action="#{accountController.moveUserUp(user)}" />
<h:commandLink id="Link2" value="Down" action="#{accountController.moveUserDown(user)}" />
<h:commandLink id="Link3" value="Delete" action="#{accountController.deleteUser(user)}" />
with
public void moveUserUp(User user) {
// ...
}
public void moveUserDown(User user) {
// ...
}
public void deleteUser(User user) {
// ...
}
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?
Invoke direct methods or methods with arguments / variables / parameters in EL
The onclick attribute is used to invoke JavaScript function (client-side). It is be used when you want to attach a JavaScript click event hanlder.
"#{accountController.moveDown}" is a method-expression. And as the name suggests looks like accountController is a managed bean.
As the h:link doc says:
javax.el.ValueExpression (must evaluate to java.lang.String)
Can be a value expression that must ultimately evaluate to a string.
Javascript code executed when a pointer button is clicked over this element.
Update:
May be what you are looking for is h:commandLink. You can use the action attribute to invoke the backing bean method.
I have modified your code, let me know if this is what you are looking at achive
<h:form>
<a4j:outputPanel id="userList" ajaxRendered="false">
<ui:repeat value="#{manageUser.userList}" var="user">
<div class="user">
<h:panelGrid columns="3">
<h:outputText value="#{user.userId} ---- #{user.userName} ---- " />
<a4j:commandLink id="LinkUp" value="Up" execute="#this"
action="#{manageUser.moveUserUp}" limitRender="true" render="userList" >
<f:setPropertyActionListener value="#{user}" target="#{manageUser.user}" />
</a4j:commandLink>
<a4j:commandLink id="LinkDown" value="down"
action="#{manageUser.moveUserDown}" execute="#this" limitRender="true" render="userList" >
<f:setPropertyActionListener value="#{user}" target="#{manageUser.user}" />
</a4j:commandLink>
</h:panelGrid>
</div>
</ui:repeat>
</a4j:outputPanel>
</h:form>
Managed Beans (ManageUser)
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name="manageUser")
#ViewScoped
public class ManageUser implements Serializable {
/**
*
*/
private static final long serialVersionUID = -5338764155023244249L;
private List<UserBean> userList;
private UserBean user;
/**
* #return the user
*/
public UserBean getUser() {
return user;
}
/**
* #param user the user to set
*/
public void setUser(UserBean user) {
this.user = user;
}
/**
* #return the userList
*/
public List<UserBean> getUserList() {
return userList;
}
/**
* #param userList the userList to set
*/
public void setUserList(List<UserBean> userList) {
this.userList = userList;
}
public ManageUser() {
UserBean user1= new UserBean();
user1.setUserId("1");
user1.setUserName("userName1");
UserBean user2= new UserBean();
user2.setUserId("2");
user2.setUserName("userName2");
UserBean user3= new UserBean();
user3.setUserId("3");
user3.setUserName("userName3");
userList = new ArrayList<UserBean>();
userList.add(user1);
userList.add(user2);
userList.add(user3);
}
public void moveUserDown(){
if(user !=null){
int indexObj= userList.indexOf(user);
if(indexObj < userList.size()-1){
UserBean tempUser=userList.get(indexObj+1);
userList.set(indexObj+1, user);
userList.set(indexObj, tempUser);
}
}
}
public void moveUserUp(){
if(user !=null){
int indexObj= userList.indexOf(user);
if(indexObj > 0){
UserBean tempUser=userList.get(indexObj-1);
userList.set(indexObj-1, user);
userList.set(indexObj, tempUser);
}
}
}
}
UserBean
import java.io.Serializable;
public class UserBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 3820279264217591645L;
private String userName;
private String userId;
/**
* #return the userName
*/
public String getUserName() {
return userName;
}
/**
* #param userName the userName to set
*/
public void setUserName(String userName) {
this.userName = userName;
}
/**
* #return the userId
*/
public String getUserId() {
return userId;
}
/**
* #param userId the userId to set
*/
public void setUserId(String userId) {
this.userId = userId;
}
}
I have a JSF page which renders a text field depending on the value of a drop down using primefaces ajax listner. The dynamic rendering is done fine. but the problem is once I submit the form the the bound value of that textfield doesn't get bound instead it is shown as null.
this is the part of my JSF only the necessary fields are included here
<h:panelGroup id="textPanel" >
<h:form id="main" prependId="false">
<h:outputText value="WorkFlow ID:" />
<h:selectOneMenu id="workFlows" value="#{workFlowSelectionController.selectedWorkFlowId}" >
<p:ajax event="change" listener="#{workFlowSelectionController.dropDownChange}" update="textPanel"/>
<f:selectItems value="#{workFlowSelectionController.allActiveworkFlows}"/>
</h:selectOneMenu>
<p:inputText value="#{workFlowSelectionController.texField}" rendered="#{workFlowSelectionController.textfieldVisibility}"/>
<p:commandButton ajax="false" value="Next" action="#{workFlowSelectionController.addWorkFlowselectionDetails}"/>
</h:form>
</h:panelGroup>
this is my managed bean
#ManagedBean
#RequestScoped
public class WorkFlowSelectionController {
private boolean textfieldVisibility = false;
private String texField;
public void dropDownChange() {
logger.info("WorkFlowSelectionController.dropDownChange() entered");
if (selectedWorkFlowId != null) {
if (selectedWorkFlowId.equals("-1")) {
textfieldVisibility = true;
operationListStatus = false;
} else {
textfieldVisibility = false;
operationListStatus = true;
}
} else {
textfieldVisibility = false;
operationListStatus = true;
}
public void addWorkFlowselectionDetails() throws CloneNotSupportedException {
System.out.println("Selected Value of Text Field is" + texField);
}
public String getTexField() {
return texField;
}
public void setTexField(String texField) {
this.texField = texField;
}
}
i haven't included the dropdown code of the backing bean. i just need an idea of what i am doing wrong here if i remove the rendered attribute of the textfield it works fine.
thank you
Put the bean in the view scope instead of request scope. A request scoped is recreated on every single HTTP request. The boolean property will default to false again whenever you submit the form, so the submitted value won't be processed then.
#ManagedBean
#ViewScoped
public class WorkFlowSelectionController {
//
}
A view scoped bean will live as long as you're (ajax-) interacting with the same view by returning null or void from action(listener) methods.