change <h:outputText> into <h:inputText> ajax in PrimeFaces - jsf

I'm trying to make something that change <h:outputText> into <h:inputText> after clicking on button or link. Somtehing similar to this: How to build "edit" button in JSF and switch between h:outputText and h:inputText but I would like to use PrimeFaces.
I think this would be usefull: http://www.primefaces.org/showcase/ui/inplace.jsf
but I would like to make that edit mode fires after clicking on edit button or hyperlink, not after clicking on the text I want to change.
Of course after clicking edit button I would like that change to "accept" button that will allow me to save changes and change inputText into outputText

Take a look at this SSCCE, it does what you want.
TestBean.java
package com.mycompany;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
#ManagedBean
#ViewScoped
public class TestBean {
/**
* Controls if the input field is available or not
*/
private boolean editable = false;
/**
* The String value you want to edit
*/
private String value = "Default value";
/**
* Changes between the inputText and the outputText
*/
public void changeEditable() {
editable = !editable;
}
public String getValue() {
return value;
}
public boolean isEditable() {
return editable;
}
/**
* Definitely saves the value
*/
public void saveValue() {
FacesMessage message = new FacesMessage("Value " + value + " saved!");
FacesContext.getCurrentInstance().addMessage(null, message);
}
public void setEditable(boolean editable) {
this.editable = editable;
}
public void setValue(String value) {
this.value = value;
}
}
index.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>JSF Demo</title>
</h:head>
<h:body>
<p:messages />
<h:form>
<h:panelGroup rendered="#{!testBean.editable}">
<h:outputText value="#{testBean.value}" />
</h:panelGroup>
<h:panelGroup rendered="#{testBean.editable}">
<p:inputText value="#{testBean.value}" />
</h:panelGroup>
<p:commandButton
value="#{testBean.editable ? 'Confirm value' : 'Change value'}"
update="#form" actionListener="#{testBean.changeEditable}" />
<p:commandButton value="Save value" ajax="false"
action="#{testBean.saveValue}" />
</h:form>
</h:body>
</html>

Related

how to display a primefaces progressbar in a dialog

I am trying to display a progressbar in a dialog for a long operation called from the menu. The dialog does not show up. I am not sure what I am missing. Any help is much appreciated.
MainPage.xhtml -> contains the menu bar which has the longOperation menuitem
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<body>
<h:form>
<p:menubar model="#{progressBarExample.model}" styleClass="menubar"
autoDisplay="False" style="margin-bottom:5px;" />
</h:form>
</body>
</html>
progress.xhtml -> contains the progress dialog
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<body>
<p:dialog id="progressDialog" widgetVar="progressDialogVar"
modal="true" draggable="true"
resizable="false" header="Progress" >
<h:form>
<p:panel widgetVar="progressPanelVar">
<h:panelGrid id="ProgressPanel" columns="1"
style="margin-bottom:10px" cellpadding="5" width="500px">
<p:progressBar widgetVar="progressbar"
style="height:20px;width:100%;"
mode="indeterminate" />
</h:panelGrid>
</p:panel>
</h:form>
</p:dialog>
</body>
</html>
ProgressBarExample.java contains the backing bean which calls the longOperation and the Progress dialog.
#Named
#ViewScoped
public class ProgressBarExample implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private MenuModel model;
public ProgressBarExample() { }
#PostConstruct
protected void init() {
model = new DefaultMenuModel();
DefaultMenuItem item = new DefaultMenuItem();
item = new DefaultMenuItem();
item.setValue("Long Operation");
item.setCommand("#{progressBarExample.longOperation}");
model.addElement(item);
}
public void longOperation(ActionEvent ae) {
System.out.println("this is a long operation...");
PrimeFaces.current().executeScript("PF('progressDialogVar').show();");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
PrimeFaces.current().executeScript("PF('progressDialogVar').hide();");
}
public MenuModel getModel() {
return model;
}
public void setModel(MenuModel model) {
this.model = model;
}
}
As Primefaces docs stated:
PrimeFaces executeScript provides a way to execute javascript when the
ajax request completes
So, basically, what you can see is: longOperation is called, it does is work and, only after that, you show the progress bar and hide it immediately after, so you see nothing, except if you inspect your browser console.
To achieve your goal you can define your menu item like this:
DefaultMenuItem item = new DefaultMenuItem();
item = new DefaultMenuItem();
item.setValue("Long Operation");
item.setCommand("#{progressBarExample.longOperation}");
item.setOnstart("PF('progressDialogVar').show()");
item.setOncomplete("PF('progressDialogVar').hide()");
model.addElement(item);
Primefaces docs

Affect of immediate attribute, and small discrepancy in found in JSF documentation

Below is the except from JSF official documentation - The immediate Attribute
Suppose that you have a page with a button and a field for entering
the quantity of a book in a shopping cart. If the immediate attributes
of both the button and the field are set to true, the new value
entered in the field will be available for any processing associated
with the event that is generated when the button is clicked. The event
associated with the button as well as the events, validation, and
conversion associated with the field are all handled when request
parameter values are applied.
If the button's immediate attribute is set to true but the field's
immediate attribute is set to false, the event associated with the
button is processed without updating the field's local value to the
model layer. The reason is that any events, conversion, and validation
associated with the field occur after request parameter values are
applied.
This suggests that, if immediate attribute is set TRUE for input component like textbox and command component then submit button then textbox value will be available for processing, however I think this isn't true, if immediate attribute of the submit button is true, then any data entered by the user on the form is not available for processing because event handling of the submit button will occur during the "apply request values" phase and will result in form submission, so it means that "update data model" phase will not be executed and hence managed bean properties will not be updated with the data entered by the user.
I even tried out this with code and my understanding looks true. However since the excerpt is from official Oracle documentation so I would like to know if I am missing something.
Below is my code sample:
greeting.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
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>
<title>Guess Number Facelets Application</title>
</h:head>
<h:body>
<h:form>
<h:graphicImage value="#{resource['images:OracleLogo.png']}"
alt="Duke waving his hand" />
<h2>
Hi, my name is #{userNameBean.lName}, #{userNameBean.fName}. I am thinking of a number from
#{userNumberBean.minimum} to #{userNumberBean.maximum}. Can you guess it?
</h2>
<p>
User number: <h:inputText id="userNo" title="Enter a number from 0 to 10:" value="#{userNumberBean.userNumber}">
<f:validateLongRange minimum="#{userNumberBean.minimum}" maximum="#{userNumberBean.maximum}" />
</h:inputText><br></br>
User fName: <h:inputText id="userFName" value="#{userNameBean.fName}" immediate="true" required="true"/><br></br>
User lName: <h:inputText id="userLName" value="#{userNameBean.lName}" immediate="true"/><br></br>
<h:commandButton id="submit" value="Submit" action="#{userNameBean.submitRequest}" immediate="true"/>
</p>
<h:message showSummary="true" showDetail="false"
style="color: #d20005;
font-family: 'New Century Schoolbook', serif;
font-style: oblique;
text-decoration: overline"
id="errors1" for="userNo" />
</h:form>
</h:body>
</html>
response.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
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>
<title>Guess Number Facelets Application</title>
</h:head>
<h:body>
<h:form>
<h:graphicImage value="#{resource['images:OracleLogo.png']}"
alt="Duke waving his hand" />
<h2>
<h:outputText id="result" value="${'hip' lt 'hit'}" /><br></br>
<h:outputText id="result2" value="#{userNumberBean.response}" /><br></br>
<h:outputText id="result3" value="#{userNameBean.lName}" />, <h:outputText id="result4" value="#{userNameBean.fName}" />
</h2>
<h:commandButton id="back" value="Back" action="greeting" />
</h:form>
</h:body>
</html>
UserNumberBean:
import java.io.Serializable;
import java.util.Random;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named
#SessionScoped
public class UserNumberBean implements Serializable {
private static final long serialVersionUID = 5443351151396868724L;
Integer randomInt = null;
Integer userNumber = null;
String response = null;
private int maximum = 10;
private int minimum = 0;
public UserNumberBean() {
Random randomGR = new Random();
randomInt = new Integer(randomGR.nextInt(maximum + 1));
System.out.println("Duke's number: " + randomInt);
}
public void setUserNumber(Integer user_number) {
userNumber = user_number;
}
public Integer getUserNumber() {
return userNumber;
}
public String getResponse() {
if ((userNumber == null) || (userNumber.compareTo(randomInt) != 0)) {
return "Sorry, " + userNumber + " is incorrect.";
} else {
return "Yay! You got it!";
}
}
public int getMaximum() {
return (this.maximum);
}
public void setMaximum(int maximum) {
this.maximum = maximum;
}
public int getMinimum() {
return (this.minimum);
}
public void setMinimum(int minimum) {
this.minimum = minimum;
}
}
UserNameBean:
package com.db.nsw.izt;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
#Named
#RequestScoped
public class UserNameBean {
private String fName = "";
private String lName = "";
public String getfName() {
return fName;
}
public void setfName(String fName) {
this.fName = fName;
}
public String getlName() {
return lName;
}
public void setlName(String lName) {
this.lName = lName;
}
public String submitRequest(){
System.out.println("### " + fName + " | " + lName);
return "response";
}
}
UPDATE 1:
My environment details: JEE6, JSF 2.0, Mojara, WL 12.1.2 (glassfish.jsf_1.0.0.0_2-1-20.jar)

Button does not add an item to a selectManyList

I have a JSF page with a h:selectManyList and a Primefaces commandButton. I want to add new elements to the list when I click the button. The button's action method is called, but elements don't show up in the list. I probably just don't see the forest for the trees.
Page:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head/>
<h:body>
<h:form id="form">
<h:messages id="errors"/>
<h:selectManyListbox id="listBox" value="#{testBean.availableThings}" style="width:100%">
<f:selectItems value="#{testBean.selectedThings}"/>
</h:selectManyListbox>
<br/>
<p:commandButton id="adder" value="Add" action="#{testBean.addThing}"
ajax="true" update="listBox" process="#this listBox"/>
</h:form>
</h:body>
</html>
Backing bean:
import java.util.ArrayList;
import java.util.List;
import javax.faces.model.SelectItem;
#javax.faces.bean.ManagedBean
#javax.faces.bean.ViewScoped
#com.ocpsoft.pretty.faces.annotation.URLMapping(
id = "testbean",
pattern = "/testbean/",
viewId = "/pages/general/testbean.xhtml")
public class TestBean {
private List<SelectItem> availableThings;
private List<String> selectedThings;
public TestBean() {
availableThings = new ArrayList<>();
selectedThings = new ArrayList<>();
}
public List<SelectItem> getAvailableThings() {
return availableThings;
}
public void setAvailableThings(List<SelectItem> list) {
this.availableThings = list;
}
public List<String> getSelectedThings() {
return selectedThings;
}
public void setSelectedThings(List<String> list) {
this.selectedThings = list;
}
public void addThing() {
availableThings.add(new SelectItem("item", "item")); // I get this message
System.err.println("Added item");
}
}
Why doesn't the added item appear in the list and what do I need to do to make it appear?
You reversed the fields in the xhtml.
<h:selectManyListbox id="listBox" value="#{testBean.availableThings}" style="width:100%">
<f:selectItems value="#{testBean.selectedThings}"/>
</h:selectManyListbox>
Should be
<h:selectManyListbox id="listBox" value="#{testBean.selectedThings}" style="width:100%">
<f:selectItems value="#{testBean.availableThings}"/>
</h:selectManyListbox>

#javax.faces.view.ViewScoped call #PostConstruct on p:commandButton action from p:datatable column facet

I have a primefaces datatable where the commandButton's action addItem within the columns header facet always fires the CDI #ViewScoped beans #PostConstruct method, while the commandButton's action editItem from the column does not?!
Curiously enough this happens only, if the action methods return a non-null string?! Means, if both methods return null, the #PostConstruct method is not called, but I use a non-null string, because clicking the buttons should show a new #ViewScoped page.
The main problem in my real application is, that I do some initialization stuff within #PostConstruct, which should really happen only once during page construction!
datatable.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view>
<p:messages autoUpdate="true" showDetail="true"/>
<h:outputLabel value="Datatable Test"/>
<h:form>
<p:dataTable var="item" value="#{datatableBean.items}">
<p:column>
<f:facet name="header">
<p:commandButton value="Add Item" action="#{datatableBean.editItem(null)}"/>
</f:facet>
<p:commandButton value="Edit Item" action="#{datatableBean.editItem(item)}"/>
</p:column>
<p:column headerText="Id">
<p:outputLabel value="#{item.id}"/>
</p:column>
<p:column headerText="Name">
<p:outputLabel value="#{item.name}"/>
</p:column>
</p:dataTable>
</h:form>
</f:view>
</html>
addItem.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view>
<h:outputLabel value="Add Item"/>
</f:view>
</html>
editItem.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view>
<h:outputLabel value="Edit Item"/>
</f:view>
</html>
DatatableBean.java
package my.web.datatable;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
#ViewScoped
#Named
public class DatatableBean implements Serializable {
private List<Item> items = new ArrayList<>();
#PostConstruct
private void init() {
System.out.println(DatatableBean.class.getName() + " -> init()");
for (int i = 1; i <= 5; i++) {
items.add(new Item(i, "Item " + i));
}
System.out.println(DatatableBean.class.getName() + " <- init()");
}
public List<Item> getItems() {
return items;
}
public String editItem(Item item) {
System.out.println(DatatableBean.class.getName() + " -> editItem(): " + item);
if (item == null) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "add item", null));
System.out.println(DatatableBean.class.getName() + " <- editItem()");
return "addItem.xhtml";
} else {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "edit item", item.toString()));
System.out.println(DatatableBean.class.getName() + " <- editItem()");
return "editItem.xhtml";
}
}
}
Item.java
package my.web.datatable;
public class Item {
private final int id;
private final String name;
public Item(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
#Override
public String toString() {
return String.format("[id=%d,name=%s]", id, name);
}
}
Is this a bug regarding command button within datatable column header facet? Or is there a better way, to do what I want?
I am using primefaces 6.0 on wildfly-10.0.0.Final with Mojarra 2.2.12!
Update: removed logger; call same method for addItem / editItem; added redirect / forward pages

Primefaces composite component not rendering [duplicate]

This question already has an answer here:
Extended #FacesComponent as composite interface componentType renders nothing
(1 answer)
Closed 7 years ago.
I'm trying to build in a composite component in JSF with PrimeFaces.
in src/main/webapp/resources/components I have a component called editableLabel.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<composite:interface componentType="editableLabel">
<composite:attribute name="value" required="true"/>
<composite:attribute name="editMode" required="false" default="#{false}" type="java.lang.Boolean"/>
</composite:interface>
<composite:implementation>
<h:panelGroup id="editableLabelComponent">
<h:panelGroup rendered="#{cc.attrs.editMode}">
<p:inputText value="#{cc.attrs.value}"/>
<p:commandButton value="Update" actionListener="#{cc.update}"/>
<p:commandButton value="Cancel" actionListener="#{cc.cancel}"/>
</h:panelGroup>
<p:outputLabel id="display" value="#{cc.attrs.value}" rendered="#{!cc.attrs.editMode}">
<p:ajax event="click" listener="#{cc.toggleEditMode}" update="editableLabelComponent"/>
</p:outputLabel>
</h:panelGroup>
</composite:implementation>
</h:body>
</html>
Backed by a FacesComponent called EditableLabel.java
import javax.el.ValueExpression;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import java.io.Serializable;
/**
* Created by labraham on 1/14/16.
*/
#FacesComponent(value = "editableLabel")
public class EditableLabel extends UIComponentBase implements Serializable {
private static final long serialVersionUID = 108467781935083432L;
private String oldValue = "";
/**
* Constructor
*/
public EditableLabel() {
super();
}
#Override
public String getFamily() {
return "foo.bar.components";
}
/**
*
*/
public void update() {
toggleEditMode();
FacesContext context = FacesContext.getCurrentInstance();
this.oldValue = (String) getValueExpression("value").getValue(context.getELContext());
}
/**
*
*/
public void cancel() {
toggleEditMode();
FacesContext context = FacesContext.getCurrentInstance();
ValueExpression valueExpression = getValueExpression("value");
valueExpression.setValue(context.getELContext(), this.oldValue);
}
/**
*
*/
public void toggleEditMode() {
FacesContext context = FacesContext.getCurrentInstance();
Boolean editModeValue = (Boolean) getValueExpression("editMode").getValue(context.getELContext());
ValueExpression editModeVe = getValueExpression("editMode");
editModeVe.setValue(context.getELContext(), String.valueOf(!editModeValue));
}
}
Yet when I try to stick it in an another file like so
foo.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui" xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:comp="http://java.sun.com/jsf/composite/components"
>
...
<h3>Test</h3>
<comp:editableLabel value="#{foobean.testValue}"/>
It doesn't render. It tried removing the rendered attributes from the component (as well as editmode composite:attribute) and I've verified that it's looking for editableLabel.xhtml in the right place. foobean.testValue is just a string with a default value of "test value" and the appropriate getter and setter.
Why might PrimeFaces refuse to render this composite component?
Edit: I've also tried replacing the primefaces components in the composite component with their JSF equivalents and that didn't work. And I tried removing the ajax calls to see if maybe it was some issue with that. It wasn't.
Edit 2: Its an issue the my FacesComponent but I don't know what. Removing the component type attribute got it to render at least.
So I figured it out thanks to BalusC's answer to Extended #FacesComponent as composite interface componentType renders nothing
I needed to implement NamingContainer and getFamily() in EditableLabel.java

Resources