i am getting problem in editing in textBox which are generated dynamically.
see my code.
<h:form>
<h:panelGroup>
<h:panelGrid columns="2">
<h:panelGrid columns="1">
<h:selectOneRadio id="radio1" value="#{dynamicBean.radiovalue}" layout="pageDirection" >
<f:selectItems value="#{dynamicBean.objectList}" var="k1" itemValue="#{k1.value}" itemLabel="" />
</h:selectOneRadio>
</h:panelGrid>
<h:panelGrid columns="1" rowClasses="raw1">
<c:forEach items="#{dynamicBean.objectList}" var="k3">
<p:inputText value="#{k3.textvalue}" valueChangeListener="#{dynamicBean.ajaxEvent}" >
</p:inputText>
</c:forEach>
</h:panelGrid>
<h:commandButton value="add new" action="#{dynamicBean.addNew}"/>
</h:panelGrid>
</h:panelGroup>
</h:form>
and this is my bean.
#ManagedBean
#ViewScoped
public class DynamicBean implements Serializable{
private String radiovalue;
private List<Pojo> objectList=new ArrayList<Pojo>();
int i=0;
private Pojo single=new Pojo();
public DynamicBean() {
System.out.println("In Cons");
if(objectList.isEmpty())
{
Pojo p1=new Pojo();
p1.setName("Name-"+i);
p1.setValue("Value-"+i);
p1.setTextvalue("Text-"+i);
objectList.add(p1);
i++;
setRadiovalue(p1.getValue());
}
}
public void addNew()
{
Pojo p1=new Pojo();
p1.setName("Name-"+i);
p1.setValue("Value-"+i);
p1.setTextvalue("Text-"+i);
objectList.add(p1);
i++;
setRadiovalue(p1.getValue());
}
public void ajaxEvent(ValueChangeEvent e)
{
System.out.println("New:"+e.getNewValue());
System.out.print("Old:"+e.getOldValue());
}
following are three variable in Pojo with getter and setter
private String name;
private String value;
private String textvalue;
biggest confusion is i can change first object value on in text box but i cant change the value of new generated objects.
Thanks.
Your concrete problem is caused because you're using JSTL <c:forEach> tag which runs during view build time while you're using a view scoped bean. View scoped beans are stored in the view state. When you submit the form to the server, the view state will be restored, but the original view scoped bean isn't available yet at that moment and thus a new one will be created (thus, with all properties set to default!). After restoring the view, the original view scoped bean will be put back in scope, overriding the temporary one.
You need a fullworthy JSF UI component instead of a JSTL tag. For this particular purpose, you need the <h:dataTable>.
Replace
<h:panelGrid columns="1" rowClasses="raw1">
<c:forEach items="#{dynamicBean.objectList}" var="k3">
<p:inputText value="#{k3.textvalue}" valueChangeListener="#{dynamicBean.ajaxEvent}" >
</p:inputText>
</c:forEach>
</h:panelGrid>
by
<h:dataTable value="#{dynamicBean.objectList}" var="k3" rowClasses="raw1">
<h:column>
<p:inputText value="#{k3.textvalue}" valueChangeListener="#{dynamicBean.ajaxEvent}" />
</h:column>
</h:dataTable>
See also:
JSTL in JSF2 Facelets... makes sense?
Unrelated to the concrete problem, you've some code duplication there in the constructor. Just call addNew() method in there. I'd also remove the instance variable i as that makes no sense. Just use a local one instead which get initialized with List#size().
public DynamicBean() {
addNew();
}
public void addNew() {
Pojo p1 = new Pojo();
int i = objectList.size();
p1.setName("Name-" + i);
p1.setValue("Value-" + i);
p1.setTextvalue("Text-" + i);
objectList.add(p1);
setRadiovalue(p1.getValue());
}
Related
I'm using Spring Web Flow and JSF-2.
The fact is strange and incomprehensible to me.
I have a main page, a typical index.
And I have and actionView with some filters (filtering will be made with an ajax calling) and a table for displaying the results according to filter info.
The back bean for this action is definied as #ViewScoped.
If, at first, I navigate to index after filtering some data and then, later, I return to the action view I don't expect to found the last search displayed, I expect an empty view, but the filters are not empty and data result is filtered.
Why? If I'm defining a #ViewScope is due to I expect the back bean information has to be deleted when I change the view (and index is another view in my case) but I must be making some mistake.
Here is my code:
My parent-flow (simpifying):
<view-state id="index" view="../index.xhtml" redirect="true" popup="true"/>
<view-state id="action1Flow" view="flowRedirect:action1-flow" />
<global-transitions>
<transition on="home" to="index" />
<transition on="action1" to="action1Flow" />
</global-transitions>
action1-flow: (start-state="action1View")
<view-state id="action1View" view="../views/action1View.xhtml" redirect="true" popup="true"/>
action1View.xhtml: (Simplifying, one filter -> table results)
...
<p:panel id="filter" header="Filter example">
<h:panelGrid columns="2">
<h:outputLabel for="dataFilter" value="Filter"/>
<p:inputText id="dataFilter" value="#{action1View.dataValue}"/>
<p:ajax event="keyup" listener="#{action1View.filterData()}" update="table"/>
</p:inputText>
</h:panelGrid>
</p:panel>
<p:panel id="display" header="Data filtered">
<p:dataTable id="table" var="data" value="#{action1View.resultData"
selection="#{action1View.selectedData}" rowKey="#{data.dataValue}">
<p:column headerText="#{msg.id}" sortBy="#{data.dataValue}">
<h:outputText value="#{data.dataValue}" />
</p:column>
</p:dataTable>
</p:panel>
...
<p:commandButton value="Go to index" action="home"/>
...
and action1View.java, the back bean:
#ManagedBean
#ViewScoped
#Component("action1View")
public class Action1View implements Serializable {
static final long serialVersionUID = 42L;
List<ExampleBean> resultData = null;
ExampleBean selectedData = null;
Integer dataValue;
public ExampleBean getSelectedData() {
return selectedData;
}
public void setSelectedData(ExampleBean selectedData) {
this.selectedData = selectedData;
}
public Integer getDataValue() {
return dataValue;
}
public void setDataValue(Integer dataValue) {
this.dataValue = dataValue;
}
public void filterData() {
// Some logic
resultData = xxxxx;
}
}
index.xhtml:
...
<p:commandButton value="Go to index" action="action1"/>
...
Sorry for my english and ...
Greetings!
I have found the GAP!
My bean, apart from #ViewScoped annotation, is also defining (as you can see in the code) with this annotation: #Component("action1View") without apparent reason.
The fact is by removing this annotation I got everything to work properly.
I think that is because the Component behaviur overlays ViewScoped one doing that only one bean for each defined class can be created, and, becauso of this, information stays in time (until the session ends or the application was closed).
But it would be great if someone give more and richer information about it.
I have a very simple JSF 2/Facelets page that looks like this:
<ui:repeat value="#{myBean.names}" var="_name">
<h:commandLink value="#{_name}" action="#{myBean.sayHello(_name)}">
<f:ajax execute="#this"/>
</h:commandLink>
<br/>
</ui:repeat>
The backing bean provides a java.util.List<String> with names and the action-method just prints a "hello <name>" message to standard output.
This works fine. I get a list of names in the browser and a click fires the action-method that says hello to the specified name.
The Problem arises, when I want to put this code in a composite component that does the iteration and renders the actual link via a facet:
<ui:component xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:cc="http://xmlns.jcp.org/jsf/composite">
<cc:interface>
<cc:attribute name="value" type="java.util.List" required="true" />
<cc:facet name="content" />
</cc:interface>
<cc:implementation>
<ui:repeat value="#{cc.attrs.value}" var="_name">
<cc:renderFacet name="content"/>
</ui:repeat>
</cc:implementation>
</ui:component>
I use the composite component like this:
<my:myComp value="#{bean.names}">
<f:facet name="content">
<h:commandLink value="#{_name}" action="#{bean.sayHello(_name)}">
<f:ajax execute="#this"/>
</h:commandLink>
<br/>
</f:facet>
</my:myComp>
In the browser I get a list of names that looks exactly like before. But clicking a link now renders a "hello null" message. So _name is resolved correctly in the value attribute of <h:commandLink> but not in the action attribute.
I also tried using actionListener instead of action or the listener attribute from the <f:ajax> tag with no difference.
Could anybody shade some light on this issue?
My environment:
WildFly 8.1 with
JSF 2.2.6 (Mojarra)
The issue has to do with the scope of the variable in this case _name which is evaluated once when the <ui:repeat/> is being processed. In my case, I ran your code and it produced Hello John even though their were other names in my list. To get around this, I introduced a <f:param/> that would contain the value of the _name, and modified your code as follows:
<h:form>
<my:myComp value="#{bean.names}">
<f:facet name="content">
<h:commandLink value="#{_name}" action="#{bean.sayHello()}">
<f:param name="name_" value="#{_name}"/>
<f:ajax execute="#this"/>
</h:commandLink>
<br/>
</f:facet>
</my:myComp>
</h:form>
I also modified the sayHello() method as follows for a #RequestScoped bean:
#ManagedProperty(value = "#{facesContext}")
private FacesContext facesContext;
public void setFacesContext(FacesContext facesContext) {
this.facesContext = facesContext;
}
public void sayHello() {
Map<String, String> params = facesContext.getExternalContext()
.getRequestParameterMap();
String name = params.get("name_");
System.out.println("Hello " + name);
}
You could change this to something shorter in a #ViewScoped bean to:
public void sayHello() {
Map<String, String> params = FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap();
String name = params.get("name_");
System.out.println("Hello " + name);
}
The final result is that it prints out the names correctly.
I cant't understand why in my PrimeFaces view when I call
<f:setPropertyActionListener value="#{item}" target="#{tagController.current}" />
it never calls the backed bean tagController.setCurrent method.
I've the following view:
<h:form id="tableForm" styleClass="form-horizontal">
<h:panelGroup id="dataPanel">
<p:dataTable value="#{tagController.lazyModel}"
lazy="true"
id="table"
var="item"
paginator="true"
rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="10,20,50" >
<p:column headerText="Name" sortBy="#{item.name}" filterBy="#{item.name}">
<h:outputText value="#{item.name}"/>
</p:column>
<p:column>
<p:commandLink id="testButton" update=":testForm:panel" process="#this">
<h:outputText value="Test" />
<f:setPropertyActionListener value="#{item}" target="#{tagController.current}" />
</p:commandLink >
</p:column>
</p:dataTable>
</h:panelGroup>
</h:form>
<br/>
<h:form id="testForm" styleClass="form-horizontal">
<p:panelGrid columns="4" id="panel" >
<h:outputLabel value="Name: #{tagController.current.name}" />
</p:panelGrid>
</h:form>
and the following backed bean:
#ViewScoped
#Named
public class TagController implements Serializable {
#Inject
TagFacade tagFacade;
protected LazyDataModel<Tag> lazyModel;
protected ResourceBundle bundle = ResourceBundle.getBundle("resources/messages");
#Getter
protected Tag current = new Tag();
public void setCurrent(Tag current) {
System.out.println(">>>>>>>>>> THIS METHOD IS NEVER CALLED ? WHY ?");
this.current = current;
}
public LazyDataModel<Tag> getLazyModel() {
//... omitted for brevity
}
}
The datatable is working well, I see data, the paginator, filters and sorting works well but when I click the test link nothing happens (no exceptions, no javascript errors into the html page, no message print into stdout...).
I'm using Glassfish 3.1.2 / Mojarra 2.1.22 / PrimeFaces 3.5.
Someone can help me ?
Many thanks in advance...
I notice that you are mixing CDI with JSF annotations. there is no view scoped annotations for CDI.you should replace view scoped with a CDI Scope or change #named annotations to #Managedbean
<p:column>
<p:commandButton id="bb" actionListener="#{yourmanagedbean.setmyvalue(item)}"
title="Test" update=":testForm:panel">
</p:commandButton>
</p:column>
In backing bean look like this
public void setCurrent(Tag current) throws Exception {
try {
this.current = current;
} catch (Exception e) {
// ...
}
}
Try to make panelgrid inside a panel and update it.
Since you are using annotation for getter, I suspect that by default the setter will pass directly by your variable.
You should try like this
private Tag current = new Tag();
public void setCurrent(Tag current) {
System.out.println(">>>>>>>>>> THIS METHOD IS NEVER CALLED ? WHY ?");
this.current = current;
}
public Tag getCurrent() {
return this.current;
}
More info :
Lombok Getter setter
I had the same problem but with a different solution. I had the annotations correct and so on, but had a dialog (I didn't even use) that had the following code
<h:inputText value="#{aSBean.newElement.vaSl}" validatorMessage="Nr bitte numerisch eingeben">
<f:validateDoubleRange minimum="1" maximum="999" />
</h:inputText>
Somehow (still don't know why) my setter doesn't work with this piece of code in the dialog. Just adding this in case others have this problem, because it took me days to find out.
I have a page with a datatable that populates from a list. The list has many ids, which I need to pass to a bean method and perform a database operation.I am using a commandButton's rendered attribute to make a call to the bean method (findInfo()). I need to pass the ids (myBean.testList.id) one at a time from the list to this bean method so that I get the boolean back. First of, I am not sure how to pass the id (to the findInfo method in my bean), secondly if I use tag, I end up sending just a single ID. Could anyone please suggest me a solution. I tried doing it with the codes as below.
My Bean
#ManagedBean(name="myBean")
public class MyBean(){
public boolean findInfo(Integer indId){
boolean var = dataProvider.isIdPresent(indId); // database operation
if (var)
return true;
else
return false;
}
}
xhtml page
<h:dataTable value="#{myBean.testList}" var="t" >
<h:column>
<f:facet name="header">
<h:outputText value="Actions" />
</f:facet>
<h:commandButton value = "Add"
action = "#{someBean.loadReport}"
rendered = "#{myBean.findInfo() == false}"/>
<h:commandButton value = "View"
action = "#{someBean.loadReport}"
rendered = "#{myBean.findInfo() == true}"/>
</h:column>
<h:column>
...
</h:column>
</h:dataTable>
UPDATE:
I tried to follow the answer that BalusC's explained (that kolossus posted), I end up passing the id as null in f:param. Any suggestions. My updated code:
<h:dataTable value="#{myBean.testList}" var="t" >
<h:column>
<f:facet name="header">
<h:outputText value="Actions" />
</f:facet>
<h:commandButton value = "Add"
action = "#{someBean.loadReport}"
rendered = "#{myBean.findInfo() == false}">
<f:param name="id" value="#{t.id}" />
</h:commandButton>
<h:commandButton value = "View"
action = "#{someBean.loadReport}"
rendered = "#{myBean.findInfo() == true}">
<f:param name="id" value="#{t.id}" />
</h:commandButton>
</h:column>
<h:column>
...
</h:column>
My Updated Bean
#ManagedBean(name="myBean")
#RequestScoped
public class MyBean(){
#ManagedProperty("#{param.id}")
private Integer indId;
public boolean findInfo(){
boolean var = dataProvider.isIndIdPresent(indId);
if (var)
return true;
else
return false;
}
}
Also, I think I cannot use f:ViewParam as I am calling the bean from the data table within the same view.
First of all, you should declare your bean as #ViewScoped. Then, you can keep your findInfo method as following:
#ManagedBean(name="myBean")
#ViewScoped
public class MyBean(){
private List testList;
public boolean findInfo(Integer indId){ ... }
// Getters and Setters
}
The following snippet should do the job:
<h:dataTable value="#{myBean.testList}" var="t" >
<h:column>
<h:commandButton value="Add" action="#{someBean.loadReport}"
rendered="#{not myBean.findInfo(t.id)}" />
<h:commandButton value="View" action="#{someBean.loadReport}"
rendered="#{myBean.findInfo(t.id)}" />
</h:column>
</h:dataTable>
UPDATE: Since you're not using EL 2.2, you may need process the boolean value for each row before rendering the table. Wrapping the objects in the testList inside a dummy object containing a boolean value should do the job :). Something like this:
#ManagedBean(name="myBean")
#ViewScoped
public class MyBean(){
private List<DummyObject> testList;
#PostConstruct
public boolean prepareTestList(){
// Initiate test list
List<AnObject> oriList = ....;
// Process oriList to create a testList
this.testList = new LinkedList();
for (AnObject o : oriList) {
DummyObject do = new DummyObject();
do.setObject(o);
do.setIdPresent(findInfo(o.getId()));
this.testList.add(do);
}
}
public boolean findInfo(Integer indId) { ... }
public class DummyObject {
private boolean idPresent;
private AnObject object;
// Getters and Setters
}
// Getters and Setters
}
Then your rendered attribute should look like this:
<h:commandButton value="View" action="#{someBean.loadReport}"
rendered="#{t.idPresent}" />
I'm testing the component "SelectOneMenu" on a jsf page. I'm populating this component dinamically though my ManageBean (that will get all Animals from database).
I would like to know if is possible to see the user selected item of that "SelectOneMenu" (combobox), I'm trying with value="#{animalsManage.animalSelect}" but it is only called on the beginning of the page. Also, I'm using an inputText to see the value of the selected intem of the "SelectOneMenu".
What I'm doing wrong?
JSF:
<body>
<ui:component>
<h:form>
<h:outputText value="Select one Mets File" />
<h:selectOneMenu id="combo" value="#{animalsManage.animalSelected}">
<f:selectItem itemLabel="Select..." noSelectionOption="true"/>
<f:selectItems value="#{animalsManage.allAnimals}" />
</h:selectOneMenu>
<h:inputText id="textbox" value="#{animalsManage.animalSelected }" />
</h:form>
</ui:component>
</body>
ManageBean:
#ManagedBean
#ViewScoped
public class AnimalsManage implements Serializable {
#EJB
private AnimalsFacadeREST animalsFacadeREST;
private String animalSelected;
private List< SelectItem> selectAnimals;
public List<SelectItem> getAllAnimals() {
List<Animals> al = animalsFacadeREST.findAll();
selectAnimals = new ArrayList< SelectItem>();
int i = 0;
for (Animals animal: al) {
selectAnimals.add(new SelectItem(i, animal.getName()));
i++;
}
return selectAnimals;
}
public String getAnimalSelected() {
return animalSelected;
}
public void setAnimalSelected(String animalSelected) {
this.animalSelected = animalSelected;
}
}
There are many solutions to the presented problem. I present here two basic ideas.
Server-side solution. Simply attach <f:ajax> tag inside your <h:selectOneMenu> to update selected values and rerender user's choice, like in
<h:selectOneMenu id="combo" value="#{animalsManage.animalSelected}">
<f:selectItem itemLabel="Select..." noSelectionOption="true"/>
<f:selectItems value="#{animalsManage.allAnimals}" />
<f:ajax execute="combo" render="textbox" />
</h:selectOneMenu>
<h:inputText id="textbox" value="#{animalsManage.animalSelected }" />
If you like, you may also do some custom logic with selected element in ajax listener by specifying listener="#{animalsManage.performCustomAjaxLogic}" of <f:ajax> tag.
Client-side solution. Simply update element with id="textbox" on basic change event. So, if you use jQuery the solution will be
$('#combo').change(function() {
$('#textbox').val($('#combo').val());
});
Thought the client-side solution will bind only text value of your input component.