Ajax dynamically adding textbox is not working in PrimeFaces v3.5 - jsf-2

My h:form contains a p:selectOneMenu component, which has two values single and multiple. The h:form also contains a default p:inputText. My objective is to add multiple p:inputText component only when value multiple is selected. Please see the attached screenshot-
Below is my view, which suppose to send ajax request, whenever icon button is clicked-
<h:form>
<p:panel header="Dynamically Add textbox">
<p:selectOneMenu id="runType" value="#{repeateRun.runType}">
<f:selectItems value="#{repeateRun.runList}" var="runType" itemLabel="#{runType}" itemValue="#{runType}" />
<p:ajax update="outPanel" listener="#{repeateRun.renderComponent}" />
</p:selectOneMenu>
<h:panelGrid id="runList">
<ui:repeat value="#{repeateRun.runs}" var="run">
<p:inputText value="#{run.runValue}" />
</ui:repeat>
</h:panelGrid>
<p:outputPanel id="outPanel">
<p:commandButton update="runList" icon="ui-icon-plusthick" title="Add more" rendered="#{repeateRun.showAddButton}">
<f:ajax render="runList" listener="#{repeateRun.addRun}" />
</p:commandButton>
</p:outputPanel>
</p:panel>
</h:form>
The #ViewScoped #ManagedBean RepeateRun is following-
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
#ManagedBean
#ViewScoped
public class RepeateRun implements Serializable {
private static final long serialVersionUID = 1L;
private List<String> runList;
private List<Run> runs;
private int runValue;
private String runType;
private boolean showAddButton = false;
private static final String SINGLE = "Single";
private static final String MULTIPLE = "Multiple";
//Note : Getters Setters are removed while putting here
#PostConstruct
public void initBean() {
this.setRunList(this.populateRunList());
this.setRuns(this.populateRuns());
}
public void addRun() {
if (this.runs == null) {
this.setRuns(this.populateRuns());
} else {
this.runs.add(this.defaultRun());
}
}
public void renderComponent() {
if (this.getRunType().equals(SINGLE)) {
this.setShowAddButton(false);
} else {
this.setShowAddButton(true);
}
}
private List<String> populateRunList() {
List<String> runList = new ArrayList<String>();
runList.add(SINGLE);
runList.add(MULTIPLE);
return runList;
}
private Run defaultRun() {
Run defaultRun = new Run();
defaultRun.setRunValue(1);
return defaultRun;
}
private List<Run> populateRuns() {
List<Run> runs = new ArrayList<Run>();
runs.add(this.defaultRun());
return runs;
}
}
So after selecting the value Multiple in f:selectItems the plus icon button comes but the button is not invoking attached method i.e. addRun. To confirm the method addRun call after clicking, I put some sysout statements in addRun method. I saw that sysout is not flushed. At the same time I saw some xml response in the firebug.
Where is the problem?

The problem was with f:ajax which doesn't work with p:commandButton. Below are the culprit lines-
<p:commandButton update="runList" icon="ui-icon-plusthick" title="Add more" rendered="#{repeateRun.showAddButton}">
<f:ajax render="runList" listener="#{repeateRun.addRun}" />
</p:commandButton>
The above lines should be replaced with below line
<p:commandButton actionListener="#{repeateRun.addRun}" update="runList" icon="ui-icon-plusthick" title="Add more" rendered="#{repeateRun.showAddButton}" />

Related

Using backing bean value in javascript

<h:form prependId="false" id="vt_sel_form">
<p:panelGrid styleClass="center" columns="2">
<p:commandButton value="GO" oncomplete="alert(#{test.i})" actionListener="#{test.testfxn()}" update="#this"/>
</p:panelGrid>
</h:form>
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ViewScoped
#ManagedBean(name = "test")
public class TestClass implements Serializable {
int i ;
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public void testfxn() {
setI(i++);
//i=i+10;
System.out.println("i" + i);
}
}
Here, alert(#{test.i}) is always displaying 0. How do i get backing bean value that changes when I click the commandButton. It works when I click button twice. It used to work fine when I used a4j:commandButton.
That's just because alert(#{test.i}); is evaluated when the commandButton is rendered. You can see the changed value by telling JSF to render the script again:
<h:commandButton value="click me" action="#{testClass.testfxn()}">
<f:ajax render="out" />
</h:commandButton>
<h:panelGroup id="out">
<h:outputScript>
alert(#{testClass.i});
</h:outputScript>
</h:panelGroup>
Unlike Richfaces where you can directly call javascript function, primefaces you need to have javascript function as:
function_name(xhr, status, args)
Using listed CommandButton as Example:
<p:commandButton value="GO" oncomplete="alert(#{test.i})" actionListener="#{test.testfxn()}" update="#this"/>
In function test.testfxn() we have:
public void testfxn(){
RequestContext reqCtx = RequestContext.getCurrentInstance();
i = i++;
reqCtx.addCallbackParam("i", i);
}
Here,In function call to backing bean from actionlistener the variables are added to RequestContext.
Now In javascript function:
function draw(xhr, status, args) {
console.log("We are into draw function");
jsonString = JSON.parse(args.i); //json variable is taken out from args variable.
console.log("The value of i "+ i);
}

Changing language with h:graphicImage click event

I want to change the language on click one of the images. There are two image and one of them is turkish the other one is english. If I click to the english language is english. Another one is turkish with onclick.Here is my managed bean and xhtml;
public class DilSecimBean {
private boolean isTurkey = true;
private final Locale TR = new Locale("tr");
private final Locale EN = Locale.ENGLISH;
public Locale getLocale() {
if (isTurkey) {
return TR;
} else {
return EN;
}
}
public void swapLocale() {
System.out.println("SWAP LOCALE");
switchLocale();
}
private void switchLocale() {
isTurkey = !isTurkey;
Locale newLocale;
if (isTurkey) {
newLocale = TR;
} else {
newLocale = EN;
}
FacesContext.getCurrentInstance().getViewRoot().setLocale(newLocale);
}
}
Here is my xhtml;
<h:panelGrid columns="3" border="0">
<h:outputText value="Dil seçimi : " />
<h:graphicImage alt="JSF"
url="/resimler/tb.png"
width="20" height="20">
<f:ajax event="click" execute="#{dilSecimBean.swapLocale()}"/>
</h:graphicImage>
<h:graphicImage alt="JSFS"
url="/resimler/ib.png"
width="20" height="20">
<f:ajax event="click" execute="#{dilSecimBean.swapLocale()}"/>
</h:graphicImage>
</h:panelGrid>
When I click to the image there is no change on the language.How can I change the language with image click event?
first you should have a form to submit
second: why are yusing ajax here?
any way here is a working example
<h:form>
<h:commandLink action="#{localeChanger.turkishAction}">
<h:graphicImage library="images" name="de_flag.gif"
style="border: 0px; margin-right: 1em;"/>
</h:commandLink>
<h:commandLink action="#{localeChanger.englishAction}">
<h:graphicImage library="images"
name="en_flag.gif" style="border: 0px"/>
</h:commandLink>
</h:form>
for the managed bean:
import java.io.Serializable;
import java.util.Locale;
import javax.inject.Named;
// or import javax.faces.bean.ManagedBean;
import javax.enterprise.context.SessionScoped;
// or import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
#Named // or #ManagedBean
#SessionScoped
public class LocaleChanger implements Serializable {
public String TurkishAction() {
FacesContext context = FacesContext.getCurrentInstance();
context.getViewRoot().setLocale(new Locale("tr"));
return null;
}
public String englishAction() {
FacesContext context = FacesContext.getCurrentInstance();
context.getViewRoot().setLocale(Locale.ENGLISH);
return null;
}
}

command button works on second click and accordion first tab content is empty

I Have an accordion panel with a list of students and I have set dynamic="true", In a tabs of accordion panel, I have command button which invokes the method in backing bean.
here the content of first tab is empty and rest all is fine. To correct this ,I have set dynamic="false" now the content of tab is appearing but command button click doesnot invoke the method of backing bean on first click. Iam not sure what is happening.. Im using prime faces 3.4 and jsf2
<p:accordionPanel value="#{testBean.students}" var="stud" dynamic="true" activeIndex="#{systemManagedBean.formBean.id}">
<p:tab title="#{stud.name}" id="studId">
<p:commandButton process="#this" value="edit" icon="ui-icon-pencil" styleClass="btn-primary" style="margin-left:734px;" action="#{testBean.edit}">
<f:setPropertyActionListener target="#{testBean.stydent}" value="#{stud}"></f:setPropertyActionListener>
</p:commandButton>
I have tried proceess=#form did not make any change..
The following code is working:
The xhtml:
<h:form>
<p:accordionPanel value="#{so15320248.students}" var="student">
<p:tab title="#{student.name}">
<p:commandButton icon="ui-icon-pencil" value="Edit" actionListener="#{so15320248.edit(student)}"/>
</p:tab>
</p:accordionPanel>
</h:form>
The managed bean:
#ManagedBean(name = "so15320248")
#ViewScoped
public class SO15320248 implements Serializable {
private static final long serialVersionUID = -2285963068688871710L;
private List<Student> students;
#PostConstruct
public void init() {
students = new ArrayList<Student>();
students.add(new Student("Student 1"));
students.add(new Student("Student 2"));
}
public void edit(Student student) {
System.out.println("===========================");
System.out.println(student.getName());
System.out.println("===========================");
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}

Primefaces widgetVar interfering with ui:repeat or ui:datatable

I have a <ui:repeat> that iterates over a List<String> and creates a <p:commandButton> with the value of the current String in a <p:lightBox>.
But when I add widgetVar to my <p:lightBox>'s attributes the value of the <p:commandButton> is always the String from the last iteration.
Can someone explain what happens and (as I need widgetVar) maybe point out a solution?
This is my html:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head />
<h:body>
<ui:repeat var="thing" value="#{bugBean.things}">
<p:lightBox widgetVar="whatever">
<h:outputLink>
<h:outputText value="#{thing}" />
</h:outputLink>
<f:facet name="inline">
<h:form>
<p:commandButton action="#{bugBean.writeThing(thing)}"
value="#{thing}" />
</h:form>
</f:facet>
</p:lightBox>
</ui:repeat>
</h:body>
</html>
This is the backing bean:
package huhu.main.managebean;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named
#SessionScoped
public class BugBean implements Serializable {
private static final long serialVersionUID = 1L;
List<String> things = new ArrayList<String>();
public BugBean(){
things.add("First");
things.add("Second");
things.add("Third");
}
public void writeThing(String thing){
System.out.println(thing);
}
public List<String> getThings() {
return things;
}
public void setThings(List<String> things) {
this.things = things;
}
}
The widgetVar basically generates a window scoped JavaScript variable. What you're effectively doing now in JavaScript context is:
window['whatever'] = new Widget(lightboxElement1);
window['whatever'] = new Widget(lightboxElement2);
window['whatever'] = new Widget(lightboxElement3);
// ...
This way the whatever variable in JS would only refer the last one.
You should basically be giving them each an unique name, for example by adding the iteration index:
<ui:repeat var="thing" value="#{bugBean.things}" varStatus="iteration">
<p:lightBox widgetVar="whatever#{iteration.index}">
This way it becomes effectively:
window['whatever0'] = new Widget(lightboxElement1);
window['whatever1'] = new Widget(lightboxElement2);
window['whatever2'] = new Widget(lightboxElement3);
// ...
This way you can refer the individual lightboxes by whatever0, whatever1, whatever2, etc.
Unrelated to the concrete problem: isn't it easier to use a single lightbox and update its content on every click instead?
recently i had a similar problem when upgrading to primefaces 4.0 -> 5.1
I had to use syntax:
PF('whatever0')
Due to changes in how primefaces names the widgetvar.

Issue with EJB/JSF2.0

I'm currently practicing JSF and EJB, but right now I can't get the page to show the information requested, this have input text and submit button (input.xhtml) and the expected result is to show the text submitted.
/input.xhtml #16,56 value="#{welcome.name}": Target Unreachable, identifier 'welcome' resolved to null
I've tried everything to fix it, this is part of the input.xthml
<ui:define name="content">
<h:form>
<h:panelGrid columns="3">
<h:outputText value="Name:"/>
<h:inputText value="#{welcome.name}" title="name" id="name"
required="true" />
<h:message for="name" style="color: red"/>
</h:panelGrid>
<h:commandButton action="show" value="submit"/>
</h:form>
</ui:define>
</ui:composition>
This is the bean.
#ManagedBean
#RequestScoped
public class Welcome {
private String name;
private String message;
public String getMessage() {
return "Hello " + name;
}
public void setMessage(String message) {
this.message = message;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
The code looks fine and it should work just fine. I only don't see how this is related to JPA and EJB. You would have exactly the same problem when you removed JPA/EJB from your testcase, right? You can just leave those tags and this detail out of the question.
As to the concrete problem, because you omitted the import declarations, I can given the symptoms only guess that you're actually importing #ManagedBean from the javax.annotation package instead of the javax.faces.bean package. The former won't make the bean to be managed by JSF, but the latter wil do. Check and fix your imports. Note that the #RequestScoped also needs to be from the same package, not from the javax.enterprise.context package.
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean
#RequestScoped
public class Welcome {
// ...
}
write like this
#ManagedBean(name="welcome")
#RequestScoped
public class welcome implements Serializable {
private String name;
}
In html write like this
<h:inputText value="#{welcome.name}" title="name" id="name"
required="true" />

Resources