Dynamic dataTable form deletes its array when ajax is used - java

I have a dynamic dataTable that adds and removes objects. This works fine when I don't use ajax. However, when I use ajax, a problem occurs. Adding values initially is fine. However, when I start deleting objects, when I delete the last object, the items list gets deleted as well and becomes null. I am using jsf 2.2 with primefaces. I'm not sure what's causing this problem. My code is as follows.
item.xhtml
<h:panelGroup id="list">
<h:dataTable value="#{item.items}" var="object">
<h:column>
<!-- Figure out what these facets are or delete them -->
<f:facet name="keys">Keys</f:facet>
<p:inputText value="#{object.x}" />
</h:column>
<h:column headerText="Values">
<f:facet name="values">Values</f:facet>
<p:inputText value="#{object.y}" />
</h:column>
<h:column>
<h:commandLink value="Delete" action="#{user.removeObject(object)}">
<f:ajax execute="#form" render="#form" />
</h:commandLink>
</h:column>
</h:dataTable>
<h:commandButton value="add" action="#{user.addObject}">
<f:ajax execute="#form" render="#form" />
</h:commandButton>
</h:panelGroup>
item.java
#ManagedBean
#ViewScoped
public class Item implements Serializable{
public void addObject(){
Pair<String,String> tempPair = new Pair<String,String>("","");
items.add(tempPair);
return;
}
public void removeObject(Pair<String,String> i){
items.remove(i);
return;
}
}
UPDATE 1
I tried using jsf 2.1 instead, changing my viewAction to preRenderView, and my code works fine.

I think ajax is missing update properties. Try this:
<f:ajax execute="#form" render="#form" update="#form"/>

This is a bug in jsf 2.2.0. I replaced javax-faces-2.2.0.jar with javax-faces-2.2.1.jar and the issue disappeared.
Alternatively, another solution is to replace the <f:ajax> above with:
<f:ajax execute="#form" render=":form:list">
Apparently, the ajax call works fine in jsf 2.2.0 as long as the the whole form is not rendered.

Related

JSF 1.1 Datatable CRUD operation

We have a old application running with JSF 1.1, cannot upgrade due to client specification.
I would like to know is it possible to have a datatable with JSF 1.1 and upon clicking a button or link in datatable row open a dialog popup and do CRUD operation?
Thanks
Edit 1
I guess Apache Trinidad supports JSF 1.1. Can I do CRUD operation with Trinidad?
I think using Richfaces 3.1.6 (JSF 1.1 compatible) with the great A4J, will help you doing so:
<h:form id="myForm">
<rich:dataTable width="100%" style="border:none;margin-left:15px;" id="tableId" columnClasses="colClass"
value="#{managedBean.someList}" var="someVar">
<h:column> some content for this column </h:column>
<h:column>
<a4j:commandLink styleClass="linkClass" value="Delete" reRender="myForm:myModal" ajaxSingle="true" oncomplete="#{rich:component('myForm:myModal')}.show()" actionListener="#{managedBean.someMethodToUpdateDTO}">
<a4j:actionparam value="#{someVar.idForExample}" name="someName" assignTo="#{managedBean.someDTOObjectToBeUpdated.id}"/>
</a4j:commandLink>
</h:column>
</rich:dataTable>
<rich:modalPanel id="panel" width="350" height="100">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="Are you really, really sure to delete this one!!! #{managedBean.someDTOObjectToBeUpdated.name}"></h:outputText>
</h:panelGroup>
</f:facet>
<a4j:commandButton styleClass="btnClass" value="Oui" ajaxSingle="true" oncomplete="#{rich:component('myForm:myModal')}.hide()" reRedner="myForm:tableId" action="#{managedBean.deleteIt}">
</rich:modalPanel>
</h:form>
someMethodToUpdateDTO is a method, in your managed bean that looks like this:
public void someMethodToUpdateDTO(ActionEvent event){
//In this method I just load the object from somewhere else
someDTOObjectToBeUpdated = someDAO.getObject(someDTOObjectToBeUpdated.getId());
//someDTOObjectToBeUpdated is an attribute of your managed bean, of course with its getter and setter
}
Hope this helps,
Cheers

Is it possible to have a form with validation and to use rich:modalPanel for data entry too?

Richfaces 3.3.3, Jsf 1.2:
I have a a4j:form that uses some simple validation, mainly required="true" to ensure the form does not get submitted without some necessary data.
I also have some complex data to add (optionally) to the form, so I thought the best way to do this is to have a a4j:commandButton that displays a rich:modalPanel where the user can create the complex data set.
The created data is also displayed in a h:selectManyListbox that is reRendered when the modalPanel is closed.
That's the plan, at least. I have the following problems:
reRender works, but only if I prevent validation via immediate="true" - which in turn seems to prevent the selected data from the modalPanel to be present in the backing Bean
if I remove the immediate tag, the data gets updated, but only if there are no validation errors
What is the best way to get this to work the way I want? Is there another, better way?
UPDATE:
The Validation that fails is in some different part of the form, not in the data entered via the modalPanel, which is displayed in the Listbox
CODE:
modalPanel:
<rich:modalPanel id="addTrimming" domElementAttachment="parent" width="150" height="130">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="Define Filter" />
</h:panelGroup>
</f:facet>
<f:facet name="controls">
<h:panelGroup>
<h:graphicImage value="/images/close.gif" styleClass="hidelink" id="hidelinkAddTrimming"/>
<rich:componentControl for="addTrimming" attachTo="hidelinkAddTrimming" operation="hide" event="onclick"/>
</h:panelGroup>
</f:facet>
<h:panelGrid id="trimsettings" columns="3">
<h:outputText value="Target:" style="font-weight:bold"/>
<h:inputText id="target" label="XML Filename" required="true" value="#{xmlCreator.trimTarget}">
</h:inputText>
<h:outputText value=""/>
<h:outputText value="Mode:"/>
<h:selectOneMenu value="#{xmlCreator.trimMode}">
<f:selectItem itemLabel="Quality" itemValue="quality"/>
<f:selectItem itemLabel="after Primer" itemValue="afterPrimer"/>
<f:selectItem itemLabel="fixed" itemValue="fixed"/>
<f:selectItem itemLabel="Median length" itemValue="median"/>
<f:selectItem itemLabel="Motif" itemValue="motif"/>
</h:selectOneMenu>
<h:outputText value=""/>
</h:panelGrid>
<h:panelGroup>
<a4j:commandButton value="OK" action="#{xmlCreator.createTrimming}" onclick="from:submit()">
<a4j:support event="oncomplete" ajaxSingle="true" immediate="true" reRender="trimsPanel"/>
</a4j:commandButton>
</h:panelGroup>
</rich:modalPanel>
relevant form part:
<h:outputText value="Trimming:"/>
<a4j:outputPanel id="trimsPanel">
<h:selectManyListbox id="trims" value="#{xmlCreator.selectedTrimmings}">
<f:selectItems value="#{si:toSelectTrimmingList(xmlCreator.trimmings)}"/>
</h:selectManyListbox>
</a4j:outputPanel>
<a4j:commandButton id="addTrimButton" immediate="true" value=" + Trimming">
<rich:componentControl for="addTrimming" attachTo="addTrimButton" operation="show" event="onclick"/>
</a4j:commandButton>
If you do it in one form than you should separate it into two: one will be your main form and another will be form inside modal panel. Thus you'll be able to submit modal panel independently of main form and your submit button in modal panel will look like this:
<a4j:commandButton value="OK" action="#{xmlCreator.createTrimming}" reRender="trimsPanel"/>
you should use process with immediate to send modalpanel's data to bean when closing panel with a a:commandButton or a:commandLink.
for this, modal panel data has to be valid as expected, so you will get valid new data and add it to h:selectManyListBox 's bean value and reRender h:selectManyListBox.
this should work. if not please post your a:form and modalPanel code full to check.

How to invoke a method with Openfaces/JSF without rendering page?

I am trying to invoke a Save method in a bean with Openfaces 3. While Firefox is not rendering the page, Internet Explorer does.
I'm currently using this code lines:
<o:commandLink value="Save" action="#{beanX.save}">
<h:graphicImage url="/images/save_48.png" />
</o:commandLink>
but I was trying o:ajax as well:
<o:commandLink value="Save" action="#{beanX.save}">
<h:graphicImage url="/images/save_48.png" />
<o:ajax event="click" render="#none" />
</o:commandLink>
Any ideas?
I've found a way to deal with using standard JSF components. Any ideas how to solve this issue with o:commandLink?
You can use <f:ajax> and render attribute in jsf2.0
<h:form>
<h:inputText value="#{managedBean.val1}" >
<f:ajax event="keyup" render="result" listener="#{managedBean.someThingToDoListener}"/>
</h:inputText>
<h:inputText value="#{managedBean.val2}" >
<f:ajax event="keyup" render="result" listener="#{managedBean.someThingToDoListener}"/>
</h:inputText>
<h:outputText id="result" value="#{managedBean.result}"/>
</h:form>
#ManagedBean(name = "managedBean")
public class Bean {
private String val1; // getter and setter
private String val2; // getter and setter
private String res; // getter and setter
...
public void someThingToDoListener(AjaxBehaviorEvent event) {
//res = some processing
}
}
Also See
how-to-update-a-value-displayed-in-the-page-without-refreshing
JSF2: Ajax in JSF – using f:ajax tag
Thank you Jigar Joshi. You've given me the key hint. It works with this code lines:
<h:commandLink value="Save">
<h:graphicImage url="/images/save_48.png" />
<f:ajax event="click" render="#none" listener="#{beanX.save}" />
</h:commandLink>
I've been to this website before, I was not thinking in assuming that o:commandLink might not be able to handle this, might be a bug?
Using h:commandLink instead of o:commandLink and f:ajax with the listener attribute solved my problem.

JSF - Change panelGroup by using ajax calls - Beans, EL and?

I have to make a sort of switch of some panelGroup UI.
About the view section, i made this :
<h:panelGroup layout="block" id="profile_content">
<h:panelGroup layout="block" styleClass="content_title">
Profilo Utente
</h:panelGroup>
<h:panelGroup rendered="#{selector.profile_page=='main'}">
<ui:include src="/profile/profile_main.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{selector.profile_page=='edit'}">
<ui:include src="/profile/profile_edit.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{selector.profile_page=='insert'}">
<ui:include src="/profile/profile_articles.xhtml" />
</h:panelGroup>
</h:panelGroup>
Now, to change this value, i written an exclusive JavaBean, called Selector :
#ManagedBean(name="selector")
#RequestScoped
public class Selector {
#ManagedProperty(value="#{param.profile_page}")
private String profile_page;
public String getProfile_page() {
if(profile_page==null || profile_page.trim().isEmpty()) {
this.profile_page="main";
}
return profile_page;
}
public void setProfile_page(String profile_page) { this.profile_page=profile_page; }
}
So, right now succeeds my problem : when i change the "context" by using some h:commandButton, i'd like to use asynch call to the server. This is my Button Panel :
<h:commandButton value="EDIT">
<f:ajax event="action" execute="???" render=":profile_content"/>
</h:commandButton>
<h:commandButton value="PM">
<f:ajax event="action" execute="???" render=":profile_content"/>
</h:commandButton>
<h:commandButton value="ARTICLES">
<f:ajax event="action" execute="???" render=":profile_content"/>
</h:commandButton>
I don't know what to put on execute, so that i edit the Beans value and i change the context by using render=":profile_content"
Hope this question is comprehendible. Forgive me about language :)
Cheers
Use f:setPropertyActionListener. You don't need to override the default of f:ajax's execute attribute (which is #this, the sole button).
E.g.
<h:commandButton value="EDIT">
<f:setPropertyActionListener target="#{selector.profile_page}" value="edit" />
<f:ajax event="action" render=":profile_content"/>
</h:commandButton>
Note that the Java Coding Conventions recommends CamelCase over under_score. I'd suggest to fix profile_page to be profilePage. This is Java, not PHP.

reRendering is not happening in jsf using data table

Rerendering is not working in my code:
<rich:simpleTogglePanel id="bookIncomeHeader1" value="#{myBean.ftBoookIncomelst}"
label="BOOK INCOME" bodyClass="STP" style="ReptxtBold Reptxt_LtPad"
switchType="server">
<rich:dataTable id="bookIncome" value="#{myBean.ftBoookIncomelst}" var="item"
rowKeyVar="row" first="0" width="100%">
<rich:subTable id="subBookIncome"value="#{item.txIncome}" var="income"
rowKeyVar="row">
<rich:column id="descrtiptionColumn" width="30%">
<h:outputText value="#{income.descriptionCell.value}"
rendered="#{!item.editableRow}"
style="#{income.descriptionCell.boldClass}" />
<rich:inplaceInput layout="block" required="true"
value="#{income.descriptionCell.value}"
rendered="#{item.editableRow}"
requiredMessage="Description at row #{row+1} wasn't filled."
changedHoverClass="hover" viewHoverClass="hover"
viewClass="inplace" changedClass="inplace"
selectOnEdit="true" editEvent="onclick" />
</rich:column>
In the above code I have proper id for datatable and I'm calling my ajax call using:
<rich:menuItem value="Add Manual Adjustment" id="addmanualadjust">
<a4j:support event="onclick" action="#{myBean.addNewDataItem}"
reRender="bookIncome">
<f:param name="rowNum" value="#{item.serialNum}"></f:param>
</a4j:support>
</rich:menuItem>
It's hitting the server and calling proper method and updating the required list, but it's not showing any response. Why is it not rendering? It does not show any exception on console either.
the a4j:support and the dataTable should be in the same <x:form>
try adding immediate="true" to the a4j:support to bypass validation errors.
Does it work if you rerender bookIncomeHeader1?
Max
http://mkblog.exadel.com

Categories