Primefaces picklist target and source values do not change - java

My primefaces pickList source and target values do not change, I have followed the example in primefaces showcase
and also looked at several posts here but still am not able to solve the problem. I am using a list from the database to populate the source as follows:
private DualListModel<Course> courseModel;
public CourseBean() {
List<Course> target = new ArrayList<Course>();
List<Course> source = new ArrayList<Course>();
courseModel = new DualListModel<Course>(source, target);
}
...
//this DualListModel getter also populates the source with values from db
public DualListModel<Course> getCourseModel() {
courseModel.setSource(getCourseList());
return courseModel;
}
My converter is
import org.omnifaces.converter.SelectItemsConverter;
#FacesConverter("courseConverter")
public class CourseConverter extends SelectItemsConverter {
#Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
Integer id = (value instanceof Course) ? ((Course) value).getId()
: null;
return (id != null) ? String.valueOf(id) : null;
}
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String value) {
Course course = new Course();
course.setId(Integer.parseInt(value));
return course;
}
}
and finally my xhtml page is:
<h:form>
<p:pickList id="coursesOffered"
value="#{courseView.courseModel}" var="course"
itemValue="#{course}" itemLabel="#{course.courseTitle}"
converter="courseConverter" showSourceFilter="true"
showTargetFilter="true" filterMatchMode="contains">
<f:facet name="targetCaption">Selected</f:facet>
<f:facet name="sourceCaption">All Courses</f:facet>
<p:ajax event="transfer" listener="#{courseView.onTransfer}" />
<p:column style="width:10%">
#{course.courseCode}:
</p:column>
<p:column style="width:90%">
#{course.courseTitle}
</p:column>
</p:pickList>
<p:commandButton id="pojoSubmit" value="Submit"
update="displayPlayers" oncomplete="playerDialog.show()"
style="margin-top:5px" />
<p:dialog showEffect="fade" hideEffect="fade" widgetVar="playerDialog">
<h:panelGrid id="displayPlayers" columns="2">
<h:outputText value="Source: " style="font-weight:bold" />
<ui:repeat value="#{courseView.courseModel.source}"
var="course">
<h:outputText value="#{course.courseTitle}"
style="margin-right:5px" />
</ui:repeat>
<h:outputText value="Target: " style="font-weight:bold" />
<ui:repeat value="#{courseView.courseModel.target}"
var="course">
<h:outputText value="#{course.courseTitle}"
style="margin-right:5px" />
</ui:repeat>
</h:panelGrid>
</p:dialog>
</h:form>
The pickList is displayed correctly with source populated with values from database, however, upon clicking the button, the dialog just displays the original source list values and an empty target list even after transferring items on the interface. What am I missing?

I see some problems with your code. In the getter, you are reconstructing the DualList from the database, reseting any changes you've done so far.
try making you getter something like this:
public DualListModel<Course> getCourseModel() {
return this.courseModel;
}
Construct and load your list from the database in a method annotated #PostConstruct rather than in the constructor+getter.
public CourseBean() {}
#PostConstruct
public void init() {
List<Course> target = new ArrayList<Course>();
courseModel.setSource(getCourseList());
courseModel = new DualListModel<Course>(source, target);
}
Also annotate your bean #ViewScoped, so you dont construct a new bean with empty target-list on every request
#ManagedBean(name="courseView")
#ViewScoped
public class CourseBean {
}
Finally you also need a setter:
public void setCourseModel(DualListModel<Course> courseModel) {
this.courseModel = courseModel;
}
I have not really looked into the converter, when I did a picklist lasttime i took the converter included in primefaces showcase (Never tried the omnifaces one). Here is a link to the source: http://code.google.com/p/ind/source/browse/indicadorCensoJSF/src/ve/gob/ine/censo/beans/convert/PrimeFacesPickListConverter.java?spec=svn154&r=154

Complementary to the accepted answer, I had a problem with the Omnifaces list converter. Everything worked, except that the already picked items weren't being updated and "lost", it is, they were there in the view but the only items processed were the picked in the view, not the ones that were already set as targets in the bean, so, instead of having a target list with the picked items plus the ones that were set at the dualList constructor, the target list had just the ones picked at the view, not the previously set items.
As a solution, I also implemented a custom picklist converter for the primefaces component. Now everything works like a charm.
I'm not answering specifically the actual question because it has an accepted answer already (and i don't have the points to make a comment). I'm just complementing, as some people may have problems using primefaces 2.3 and omnifaces 3.1. I did search a lot about the problem I was facing, and did not found at least a hint of what was happening.
This site: picklist example has a tutorial on how to make the converter, if someone has doubts. ACV's answer is also valid for the converter, although it was already implemented by Silverfish, who asked the question.

To work with objects, you need a converter. This is the best answer how to implement it: https://stackoverflow.com/a/6625392/912829

Related

JSF list depending on selected value returning nullPointer

In my jsf page, in a dialog, I have a list of EntityB which depends on selected EntityA in a datatable.
When I first load the page it's giving me nullPpointer exception because nothing is selected in the first place. Can anyone tell me how to prevent this?
EDIT: I added an actionlistener to the link who open the dialog
and getting this error:
Cannot convert DemandesDocsAdministratif type DemandesDocsAdministratif to class javax.faces.event.ActionEvent
JSF:
<p:commandLink value="#{demande.idDemandeDocAdministratif}"
oncomplete="PF('dlg2').show()" process="#this"
update=":form:pg" actionListener="#{gestionDemandesMB.fillEntityB}">
<f:setPropertyActionListener
target="#{gestionDemandesMB.SelectedEntityA}" value="#{demande}"
/>
</p:commandLink>
<form>
<datatable>
</datatable>
<p:dialog>
<p:selectOneMenu id="Signataires"
value="#{gestionDemandesMB.entityB}">
<f:selectItems value="#{gestionDemandesMB.listEntityB}"
var="sign" itemLabel="#{sign.libRole}"
itemValue="#{sign.idPoste}" />
</p:selectOneMenu>
</p:dialog>
</form>
Bean:
public List<EntityA> getListEntityB() {
if ( selectedentityA != null ){
return entityBService.ListByentityA(selectedEntityA)
; } else {
return Collections.emptyList() ; }
Bean listener that I'm working with now:
public void fillSignataires(ActionEvent event)
{
listB = entityBService.ListByentityA(selectedEntityA)
signaRender = true ;
}
this is the getter of entity B list, I'm looking for a way to either get an empty list or call only when I open dialog.
You could use rendered="#{not empty bean.list}" to prevent the rendering of the selectOnMenu until you have the object filled.
You can also add a f:selectItem with a "Select" label and empty itemValue such as itemValue = " ". By the way, never have a null list, list shouldn't be null but it can be empty. It's the best practice. So you can initialize your listEntityB as an empty list at post construct of your bean.
<p:selectOneMenu id="Signataires"
value="#{gestionDemandesMB.entityB}">
<f:selectItem itemLabel="Select" itemValue="" />
var="sign" itemLabel="#{sign.libRole}"
<f:selectItems value="#{gestionDemandesMB.listEntityB}"
var="sign" itemLabel="#{sign.libRole}"
itemValue="#{sign.idPoste}" />
</p:selectOneMenu>

JSF with gettable only

I'm trying to achieve a chat system through JSF. All text typed inside h:inputText will be stored after h:commandButton is pressed. After this, I have a table to print all data typed so far. This way, I have the following code for JSF:
<h:form>
<h:inputText id="id1" value="#{unicoBean.text}" />
<h:commandButton id="botao" value="Entrar" action="#{unicoBean.test}"
onclick="test()"
/>
</h:form>
<h:dataTable value="#{unicoBean.all}" var="msg">
<h:column>
#{msg.text}
</h:column>
</h:dataTable>
<script>
function test() {
alert("alert");
}
</script>
And this for backbean:
#ManagedBean
public class UnicoBean {
Facade f = new Facade();
public void setText(String s) throws Exception {
f.setText(s);
}
public List<Message> getAll() throws Exception {
return f.getAll();
}
public void test() {
System.out.println("bean called on jsf");
}
}
Inside h:inputText I want only to set values, not get them and throw back to html. Unfortunately, JSF says "Expression is not gettable", even when I don't want to get anything, only set, as exposed on my Bean. How I solve this?
It's not possible to achieve this using getter/setter strategy because is not part of JSF but Expression Language (EL). JSF only uses it to bind the data of the HTML components to the fields of a bean through proper getters and setters
However, you can use binding attribute via UIInput to pass the input field value as an argument to your action button:
<h:form>
<h:inputText id="id1" binding="#{input1}" />
<h:commandButton id="botao" value="Entrar" action="#{unicoBean.test(input1.value)}"
onclick="test()" />
</h:form>
And then receive the new value from your action method:
public void test(String value) {
System.out.println("bean called on jsf: " + value);
}

Adding one or more outputText to existing page dynamically

I have a need to continuously update a page with new data produced by managedbeans. Managedbean creates a new List of values for every few minutes and UI must create a OutputText for each of the value in the newly created List by managedbean. Catch is, the UI should retain the outputTexts and add new one's for every request, it should not refresh/remove old outputTexts.
My code is like below - updates the same outputText fields for each ajax call, which I need to change like mentioned above.
<c:forEach var="data" items="#{myBean.dataList}">
<p:fieldset legend="#{data}" toggleable="true" toggleSpeed="500">
<h:panelGrid columns="2" cellpadding="5" border="0">
<p:scrollPanel style="height:300px">
<p:poll interval="2" listener="#{myBean.getDataList}" update="field1 field2"/>
<h:outputText value="#{data.field1}" id="field1"/>
<h:outputText value="#{data.field2}" id="field2"/>
</p:scrollPanel>
</h:panelGrid>
</p:fieldset>
</c:forEach>
so for each ajax call, there may be few data items produced by managedbeans and for each of those item there should be a new outputText field.
You can use datalist for <h:outputText value="#{data.field1}" id="field1"/>
Make a list and use them as outputtext, yes you need some css formatting because datalist used default css. sample code
<p:poll interval="3" listener="#{yourbean.yourmethod}" update="<updatecomponet>" />
<p:dataList value="#{yourbean.tempList}" var="s" id="updatecomponet">
<p:outputLabel value="#{s}"></p:outputLabel>
</p:dataList>
Note: You need to add value in list when poll call listener. it is working in my project, let me know for anything else. Hope this will help.
Maybe not the perfect solution, but you can use a DataTable with lazy loading, the poll component can update the datatable page and you don't need to update a huge amount of components.
Edit:
xhtml
<p:dataTable var="v"
value="#{myBean.getLazyList}"
scrollRows="1"
liveScroll="true"
rows="20"
scrollHeight="300"
lazy="true"
scrollable="true"
id="tsUpdates">
<p:column>
<h:outputText value="#{v.fields1}" />
</p:column>
</p:dataTable>
Bean
public class Bean {
private LazyDataModel<MyClass> lazyList;
#Named("myBean")
#ViewScoped
#PostConstruct
public void init() {
lazyList = new LazyMyClassModel(); //where myList is your data source
}
//getters and setters
}
LazyModel
public class LazyMyClassModel extends LazyDataModel<MyClass>{
private Integer findAllCount;
public LazyMyClassModel(){
}
#Override
public List<MyClass> load(int first, int pageSize, String sortField, SortOrder sortOrder,Map<String, String> filters){
List<MyClass> myList = //your live source of data
List<MyClass> data = new ArrayList<MyClass>();
data = getSubList(MyList, first, pageSize)
if (findAllCount == null) {
findAllCount = myList.size
this.setRowCount(findAllCount);
}
return data
}
public List<MyClass> getSubList(List<MyClass> list, int fromIndex, int toIndex) {
int size = list.size();
if (fromIndex >= size || toIndex <= 0 || fromIndex >= toIndex) {
return Collections.emptyList();
}
fromIndex = Math.max(0, fromIndex);
toIndex = Math.min(size, toIndex);
return list.subList(fromIndex, toIndex);
}
}

how to set to OldValue the primefaces selectOneMenu programmatically

Java / PrimeFaces 3.5
I would like to rollback primeFaces selectOneMenu Old Value and reload it updating the component at screen.
The selectOneMenu is loaded with FIRST, SECOND , THIRD values and default value is setted with FIRST
If I change the selectOneMenu value From FIRST to THIRD, I would like to set it to FIRST again.
<p:selectOneMenu id="statusProposta"
value="#{propostaBean.propostaComercial.proposta_Status}"
items="#{propostaBean.statusProposta}"
valueChangeListener="#{propostaBean.regraStatusProposta}" >
<p:ajax event="change"
process="statusProposta" update="statusProposta" />
<f:selectItem itemLabel="" itemValue="" />
<f:selectItems value="#{propostaBean.statusProposta}" />
</p:selectOneMenu>
StatusProposta :
public enum StatusProposta { FIRST,SECOND and THIRD .....
Bean :
public void regraStatusProposta(ValueChangeEvent ev){
**I dont know how to set the old value and update it in screen.**
...
public void regraStatusProposta(ValueChangeEvent ev){
//get old value first
Object oldValue=ev.getOldValue();
}
More on ValueChangeEvent API
http://forum.primefaces.org/viewtopic.php?f=3&t=36447
resetinput
blog post: Reset Values for JSF 2.2
posted by Howard at primefaces forum
http://www.primefaces.org/showcase/ui/resetInput.jsf
public void reset() {
RequestContext.getCurrentInstance().reset("form:panel");
}
I've created this utility for PrimeFaces which checks if the component is visible, otherwise it would log a WARN on console.
public static void resetUIComponents(String... componentsId) {
for (String id : componentsId) {
if (FacesContext.getCurrentInstance().getViewRoot().findComponent(id) != null) {
PrimeFaces.current().resetInputs(id);
}
}
}
So you can use it like this:
ViewUtils.resetUIComponents("form:id1", "form:id2")

JF2 Dynamic form element doesn't remember input and page refreshes every time I add element

I am trying to make a form with options to add rows. However, after I type in some input and click the add button again, the input I enter disappears. I'm not sure what is wrong with my code. In addition, when I click the add button, the page refreshes. Is there way to stop this page refresh?
Person.java
public class Person{
private List<String> guys = new ArrayList<String>();
public List<String> getGuys() {
return guys;
}
public void setGuys(List<String> guys) {
this.guys = guys;
public void addNewItem(){
guys.add("");
}
}
form.xhtml
<h:form>
<h:panelGrid columns="2">
<h:outputText value="Guys: " />
<h:dataTable value="#{person.guys}" var="men">
<h:column>
<p:inputText value="#{men}" />
</h:column>
</h:dataTable>
<h:commandButton name="add" value="Add" action="#{person.addNewItem}" />
</h:panelGrid>
<br />
<h:commandButton name="submit" type="submit" value="Submit"></h:commandButton>
</h:form>
Provided that the bean is placed in the right scope for the functional requirement, the view scope, the only major mistake left is that you're expecting that the String class has some magic setter method.
It hasn't. The String class is immutable. The following will never work on a String:
<p:inputText value="#{men}" />
You have 2 options:
Create a real model class. You can find complete examples in the following answers:
How to dynamically add JSF components
Recommended JSF 2.0 CRUD frameworks
Set the value by row index instead:
<h:dataTable binding="#{table}" value="#{person.guys}">
<h:column>
<p:inputText value="#{person.guys[table.rowIndex]}" />
</h:column>
</h:dataTable>
(note: no additional bean property necessary for the table! the code is as-is)
This does basically a person.getGuys().add(table.getRowIndex(), submittedValue). I.e. the setter is invoked on the List itself, which works perfectly fine. See also the following related answers concerning ui:repeat:
Using <ui:repeat><h:inputText> on a List<String> doesn't update model values
How map multiple inputText to an array property?
You never update your list, you are just adding empty items. You should do something like this:
Person.java (viewscoped)
public class Person implements Serializable {
private List<String> guys = new ArrayList<String>();
private HtmlDataTable dtGuys;
public void addNewItem() {
guys.add("");
}
public void addToList(ValueChangeEvent e) {
guys.set(dtGuys.getRowIndex(), e.getNewValue().toString());
}
public String save() {
System.out.println("saving...");
for (String item : guys) {
System.out.println("item= " + item);
}
return null;
}
//gettes and setters
}
form.xhtml
<h:form id="frmPrincipal">
<h:panelGrid columns="2">
<h:outputText value="Guys: " />
<h:dataTable value="#{person.guys}" var="men" binding="#{person.dtGuys}" >
<h:column>
<p:inputText value="#{men}" valueChangeListener="#{person.addToList}" />
</h:column>
</h:dataTable>
<h:commandButton name="add" value="Add" action="#{person.addNewItem}" />
</h:panelGrid>
<br />
<h:commandButton id="submit" name="submit" value="Submit" action="#{person.save}"/>
</h:form>
Using jsf 2.0.10 and primefaces 3.5
Its because you don't have an scope for that bean, so its request scoped, so when you call the action the bean is created again, you can fix this using a sessionScope or conversationScope

Categories

Resources