prime faces after submit ajax doesn't update [duplicate] - ajax

This question already has answers here:
How can I populate a text field using PrimeFaces AJAX after validation errors occur?
(3 answers)
Closed 3 years ago.
Using PF 3.2
I faced this problem
if I submit a form and their is a required field, validation done and required messages appeared. the problem is after that if I changed the combo value that -by ajax- changes the inputtext the value doesn't change, however the listener called!
xhtml
<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>
<title>Prime Test</title>
</h:head>
<h:body style="background: #F6F6F6;">
<h:form id="idAjaxFormTest">
<f:view>
<h1> <h:outputText value="after submit ajax problem" /></h1>
<p:messages showSummary="true" autoUpdate="true" />
<p:panelGrid columns="2">
<h:outputText value="Names" />
<p:selectOneMenu value="#{ajaxTest.name}">
<f:selectItems value="#{ajaxTest.names}" var="varName"
itemLabel="#{varName}" itemValue="#{varName}">
</f:selectItems>
<p:ajax listener="#{ajaxTest.listen}" update="idXname" />
</p:selectOneMenu>
<h:outputText value="Xname" />
<p:inputText value="#{ajaxTest.xname}" id="idXname"/>
<h:outputText value="Xuser" />
<p:inputText required="true" transient="true" value="#{ajaxTest.xuser}" label="xUser" />
</p:panelGrid>
<p:commandButton value="Submit" action="#{ajaxTest.doAction}" />
</f:view>
</h:form>
</h:body>
Bean
package com.actions;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "ajaxTest")
#ViewScoped
public class AjaxTestBean implements Serializable{
private List<String> names;
private String name;
private String xname;
private String xuser;
public AjaxTestBean() {
names = new ArrayList<String>();
names.add("ahmed");
names.add("mohamed");
names.add("mahmoud");
names.add("ayman");
names.add("walid");
names.add("khalid");
}
public void listen(){
xname = "QQ "+ name;
System.out.println("Listener "+ xname);
}
public void doAction(){
System.out.println("Action Done: "+ name);
}
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getXname() {
return xname;
}
public void setXname(String xname) {
this.xname = xname;
}
public String getXuser() {
return xuser;
}
public void setXuser(String xuser) {
this.xuser = xuser;
}
}

Looks like you have run into this problem:
How can I populate a text field using PrimeFaces AJAX after validation errors occur?
Adding the following to faces-config.xml together with OmniFaces library made your select-one-menu update the inputField correctly
<lifecycle>
<phase-listener>org.omnifaces.eventlistener.ResetInputAjaxActionListener</phase-listener>
</lifecycle>
If you dont want to do it for all your components, OmniFaces has a showcase how to do it per component: http://showcase.omnifaces.org/eventlisteners/ResetInputAjaxActionListener

Related

JSF/PrimeFaces: Selection based visibility

I want to show / now show (for example) a text, based on a radio selection.
In an ajax style, no roundtrip to server.
How do I have to do this with JSF/PrimeFaces?
<h:outputText value="Show some stupid Text." id="testShowText" />
<p:selectOneRadio id="testRadio" widgetVar="testRadio" value="True" layout="grid" columns="1">
<f:selectItem itemLabel="Show Text" itemValue="True"/>
<f:selectItem itemLabel="Do NOT show Text" itemValue="False"/>
</p:selectOneRadio>
UPDATE
I managed it in my test this way, but I am not sure, if this is the "best practice", I have some doubts; do I really need a managed bean for this?:
First I created a Bean to store the selected value:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class ShowTextBean {
private boolean showBool = false;
private String showString = "False";
public ShowTextBean() {
}
public boolean isShowBool() {
return showBool;
}
public void setShowBool(boolean showBool) {
this.showBool = showBool;
}
public String getShowString() {
return showString;
}
public void setShowString(String showString) {
this.showString = showString;
}
}
Then I changed the Facelets Code to:
<p:panel id="testShowTextPanel" style="display: #{showTextBean.showString eq 'False' ? 'none' : 'block'} ">
<h:outputText value="Show some stupid Text." id="testShowText"/>
</p:panel>
<p:selectOneRadio id="testRadio" widgetVar="testRadio" value="#{showTextBean.showString}" layout="grid" columns="1">
<f:selectItem itemLabel="Show Text" itemValue="True"/>
<f:selectItem itemLabel="Do NOT show Text" itemValue="False"/>
<p:ajax update="testShowTextPanel" />
</p:selectOneRadio>

JSF 1.2 empty <h:selectManyListbox /> validation issue

I'm kind of new to JSF and I'm having trouble to understand what values JSF renders in a form after its validation fails. Im using WebSphere 7 and its default implementation of JSF, MyFaces (I think 2.0).
My xhtml looks like this:
<h:form id="form">
<h:inputText id="text" value="#{backing.text}" required="true"/>
<h:message for="text" />
<h:selectManyListbox id="options" value="#{backing.options}" required="true">
<f:selectItem itemLabel="1" itemValue="1" />
<f:selectItem itemLabel="2" itemValue="2" />
<f:selectItem itemLabel="3" itemValue="3" />
</h:selectManyListbox>
<h:message for="options" />
<h:commandButton value="Save" />
</h:form>
And my backing bean like this:
public class Backing {
private String text;
private String[] options;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String[] getOptions() {
return options;
}
public void setOptions(String[] options) {
this.options = options;
}
}
I fill the <h:inputText /> with some text.
I select two options from the <h:selectManyListbox />
I press the 'Save' button
The form is rendered with the value I entered for <h:inputText /> and with the options I selected on the <h:selectManyListbox /> (no validation messages are shown, as expected)
Now ...
I empty the <h:inputText />
I deselect the two options from the <h:selectManyListbox />
I press the 'Save' button
The form renders the <h:inputText /> empty and the <h:selectManyListbox /> with the previous options I had selected (both validation messages are shown, as expected)
As you can see, the behaviour when rendering the <h:inputText /> and the <h:selectManyListbox /> is different:
<h:inputText /> renders component's submitted value
<h:selectManyListbox /> renders bean's value
I've been trying to render <h:selectManyListbox /> with no options selected without hacking or messing my code, but had no luck.
¿Is this some bug? ¿Am I missing something?
The less hacky solution I found is to copy and re-implement the method renderOption, overriding the default MenuRenderer.
The original source is something like this as I had to decompile (version 1.2_13).
Notice that I'm pasting only the lines that actually need to be changed. If you need to use this solution you will have to copy the full contents of the method:
public class MenuRenderer extends HtmlBasicInputRenderer {
protected void renderOption(FacesContext context, UIComponent component, Converter converter, SelectItem curItem, Object currentSelections, Object[] submittedValues, HtmlBasicRenderer.OptionComponentInfo optionInfo) throws IOException {
(...)
Object valuesArray;
Object itemValue;
if (submittedValues != null) {
boolean containsValue = containsaValue(submittedValues);
if (containsValue) {
valuesArray = submittedValues;
itemValue = valueString;
} else {
valuesArray = currentSelections;
itemValue = curItem.getValue();
}
} else {
valuesArray = currentSelections;
itemValue = curItem.getValue();
}
(...)
}
}
I created CustomListboxRenderer (ListboxRenderer extends MenuRenderer) like this:
public class CustomListboxRenderer extends ListboxRenderer {
#Override
protected void renderOption(FacesContext context, UIComponent component, Converter converter, SelectItem curItem, Object currentSelections, Object[] submittedValues, HtmlBasicRenderer.OptionComponentInfo optionInfo) throws IOException {
(...)
Object valuesArray;
Object itemValue;
if (submittedValues != null) {
valuesArray = submittedValues;
itemValue = valueString;
} else {
valuesArray = currentSelections;
itemValue = curItem.getValue();
}
(...)
}
}
and then added in faces-config the next lines:
<render-kit>
<renderer>
<component-family>javax.faces.SelectMany</component-family>
<renderer-type>javax.faces.Listbox</renderer-type>
<renderer-class>CustomListboxRenderer</renderer-class>
</renderer>
</render-kit>

Autoupdate of primefaces component

What I have is this piece of xhtml Code:
<p:layoutUnit id="bottomline" position="south" gutter="0">
<h:outputText rendered=",#{not empty sprintlisteMB.getSaveStatus()}" style="float:left; color:white; font-size: 0.8em;" value="#{sprintlisteMB.getSaveStatus()}"/>
</p:layoutUnit>
sprintlisteMB.getSaveStatus() returns simply returns the String saveStatus. Now I want the outputText Component to refresh anytime saveStatus is changed.
I'm not quite sure how to implement something like that and i coudn't find anything that fits my needs.
Thanks for any help!
EDIT:
So now i have Something like this:
<p:layoutUnit id="bottomline" position="south" gutter="0">
<h:outputText style="float:left; color:white; font-size: 0.8em;"
value="#{sprintlisteMB.getSaveStatus()}" />
</p:layoutUnit>
<p:socket onMessage="handleChange" channel="/saveStatus" />
<script type="text/javascript">
function handleChange(data) {
$('.display').html(data);
}
...
package de.wdr.testtool.helfer;
import org.primefaces.push.annotation.OnMessage;
import org.primefaces.push.annotation.PushEndpoint;
import org.primefaces.push.impl.JSONEncoder;
#PushEndpoint("/saveStatus")
public class SaveStatusPushRecource {
#OnMessage(encoders = {JSONEncoder.class})
public String onChange(String status) {
return status;
}
}
...
public void setSaveStatus(final String status) {
saveStatus = status;
final EventBus eventBus = EventBusFactory.getDefault().eventBus();
eventBus.publish("/saveStatus", String.valueOf(saveStatus));
}
setSaveStatus is called from several beans anytime the changes on the database are made.
But right right now it still won't update the site. What's missing?

Why is partial-rendering failing in this particular case?

I am using Mojarra 2.2.
Here the snippet:
<h:head>
<title></title>
</h:head>
<h:body>
<h:form id="playersFormId">
<h:dataTable id="playersTableId"
value="#{ajaxBean.myMap.entrySet()}" var="t">
<h:column>
<f:facet name="header">
Delete
</f:facet>
<h:commandLink id="commandDeleteId"
immediate="true"
action="#{ajaxBean.deletePlayerAction(t.key)}">
<f:ajax render=":playersFormId:playersTableId"/>
<h:graphicImage value="/resources/default/imgs/delete.png"/>
</h:commandLink>
</h:column>
<h:column>
<f:facet name="header">
Nr
</f:facet>
#{t.key}
</h:column>
<h:column>
<f:facet name="header">
Name
</f:facet>
#{t.value}
</h:column>
</h:dataTable>
</h:form>
</h:body>
with
#Named
#ViewScoped
public class AjaxBean implements Serializable {
private Map<Integer, String> myMap = new HashMap<>();
#PostConstruct
public void init() {
myMap.put(1, "Nadal Rafael");
myMap.put(2, "Federer Roger");
myMap.put(3, "Ferer David");
myMap.put(4, "Murray Andy");
myMap.put(5, "Djokovic Novak");
myMap.put(6, "Berdych Tomas");
myMap.put(7, "Haas Tommy");
myMap.put(8, "Isner John");
myMap.put(9, "Fognini Fabio");
myMap.put(10, "Robredo Tommy");
}
public Map<Integer, String> getMyMap() {
return myMap;
}
public void setMyMap(Map<Integer, String> myMap) {
this.myMap = myMap;
}
public void deletePlayerAction(String nr) {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
Map<String, String> headers = externalContext.getRequestHeaderMap();
//determination method 1
PartialViewContext partialViewContext =
facesContext.getPartialViewContext();
if (partialViewContext != null) {
if (partialViewContext.isAjaxRequest()) {
System.out.println("THIS IS AN AJAX REQUEST (DETERMINATION 1) ...");
} else {
System.out.println("THIS IS A NON-AJAX REQUEST(DETERMINATION 1)...");
}
}
System.out.println("nr: "+nr);
if(nr!=null){
myMap.remove(Integer.valueOf(nr));
}
}
}
I see that when i click on the image link, the server-side action method is getting c/d and the record is removed from the map.
I have specified that the datatable needs to be refreshed, but it doesn't get so.
Where am I getting it wrong?
When I click on the first record, under Network Tab, I see-
& under Console Tab-

Change value of checkbox using ajax in JSF

I try to solve the following problem: i have a group of h:selectBooleanCheckbox that generates using ui:repeat:
<h:form>
<ui:repeat value="#{uiCheckboxList.list}" var="boxElement" varStatus="i">
<h:selectBooleanCheckbox id="a">
<f:attribute name="value" value="#{boxElement.enabled}"/>
</h:selectBooleanCheckbox>
<h:outputLabel value="#{boxElement.val}" for="a"/>
</ui:repeat>
</h:form>
Values and label's text stored in array list and controls by servlet:
#ManagedBean(name="uiCheckboxList")
#ApplicationScoped
public class CheckBoxListBean implements Serializable {
private ArrayList<BoxTuple> list;
// BoxTyple is class with 2 fields - val (double) and enabled (boolean)
public CheckBoxListBean() {
list = new ArrayList<>();
for(double i = -2.0; i <= 2.0; i += 0.5) {
list.add(new BoxTuple(i, false));
}
// Set first element to true
list.get(0).setEnabled(true);
}
public ArrayList<BoxTuple> getList() {
return list;
}
public void setList(ArrayList<BoxTuple> list) {
this.list = list;
}
And my problem is this: when you click on one of the h:selectBooleanCheckbox server asynchronously sent request with information about the changed box, and then change the values of the another boxes without reloading page. In other words, I need to get the behavior of radio boxes. Maybe it sounds silly, but I need to solve this problem. How can i implement this?
You can do something like this:
<h:form id="form">
<ui:repeat value="#{uiCheckboxList.list}" var="boxElement"
varStatus="i">
<h:selectBooleanCheckbox id="a">
<f:attribute name="value" value="#{boxElement.enabled}" />
<f:ajax render="form"
listener="#{uiCheckboxList.listen(boxElement)}" />
</h:selectBooleanCheckbox>
<h:outputLabel value="#{boxElement.val}" for="a" />
</ui:repeat>
</h:form>
(get rid of the varStatus if you don't use it)
public void listen(BoxTuple tuple) {
if (tuple.enabled)
for (BoxTuple t : list)
if (!t.equals(tuple))
t.setEnabled(false);
}

Resources