I have a problem with PrimeFaces calendar and ajax update.
I have a calendar and when I change the date on the UI I want to refresh another component. The problem is that the first time I change the date, the other component stays the same, but when i change the date a second time, the other component is updated with the correct value that I am expecting.
Here is my form:
<h:form>
<p:calendar
value="#{foo.dtValidade}">
<p:ajax update="criteriosDataGridTeste" event="dateSelect"
listener="#{foo.updateTeste}" />
</p:calendar>
<h:panelGroup id="criteriosDataGridTeste">
<td><h:selectOneMenu value="#{foo.idtpresult}">
<f:selectItem itemLabel="ok" itemValue="ok" />
<f:selectItem itemLabel="not ok" itemValue="not ok" />
</h:selectOneMenu></td>
</h:panelGroup>
</h:form>
I am using primefaces 3.0.1
By debugging I found out that the listener is being called before the value dtValidade is set.
But i thought it should be the other way.
Why is this happening?
A simplified version of my bean:
#ManagedBean(name = "foo")
#ViewScoped
public class Foooo {
private Date dtValidade;
private String idtpresult;
public Foooo() {
dtValidade = new Date();
idtpresult = "not ok";
}
public Date getDtValidade() {
return dtValidade;
}
public void setDtValidade(Date dt) {
this.dtValidade = dt;
}
public String getIdtpresult() {
return idtpresult;
}
public void setIdtpresult(String idtpresult) {
this.idtpresult = idtpresult;
}
public void updateTeste() {
Date now = new Date();
if (dtValidade.before(now)) {
idtpresult = "ok";
} else {
idtpresult = "not ok";
}
}
}
Am I missing anything?
Thanks in advance!
try this one
add in xhtml code in the h:form where yours calendar is
<p:remoteCommand name="rc" update="criteriosDataGrid" >
and in your ajax
<p:ajax
event="dateSelect" listener="#{foo.updateCriteria}" oncomplete="rc"/>
i dont know excatly if you need the rest of attributes of p:ajax
Related
What is the correct way to return a value from a method in a managed bean indicating a successful SQL DML operation such as INSERT or UPDATE
Based on the tutorials and some blogs I read online, it says that a good practice in returning values from a method contained in a ManagedBean is a String value of a facelet or the .xhtml page
(in other words, a view) to redirect to a webpage.
Like this.
Original version:
#ManagedBean(name="myBean")
public class MyBean{
public String register(){
String SQL = "INSERT INTO myTable(col1,col2) VALUES(?,?);
PreparedStatement ps = connection.prepareStatement(SQL);
ps.setString(1,someStringVariable1);
ps.setString(2,someStringVariable2);
ps.executeUpdate();
return "index"; //pointing to index.xhtml
}
}
How about if i want to know if the executeUpdate() method was successful?
I thought I'd just change it to something like
Modified version:
public int register(){
int isSuccessful = 0;
try{
String SQL = "INSERT INTO myTable(col1,col2) VALUES(?,?);
PreparedStatement ps = connection.prepareStatement(SQL);
ps.setString(1,someStringVariable1);
ps.setString(2,someStringVariable2);
isSuccessful = ps.executeUpdate();
}
return isSuccessful;
}
However, on the modified version I returned an int which I don't see as correct as per how JSF should work with ManagedBean (Please correct me if i'm wrong)
I asked because say I have a Twitter Bootstrap modal which has the following.
<div class="modal-body">
<h:form>
//....some code here...
<h:commandButton value="Submit" action=#{myBean.register()}
<h:outputText value=" #{myBean.whatToPutHere_ToKnowIf_addData()wasSuccessful}" />
</h:form>
</div>
I need to be able to show within the modal div that register() execution was successful.
What is the simplest and correct way to accomplish that?
I read somewhere that AJAX will help but right now, I have very little knowledge of AJAX so maybe a simple solution to this is better.
I'd appreciate any help.
Thank you.
You can use a bean variable:
#ManagedBean(name="myBean")
public class MyBean {
private boolean isSuccessful = false;
public boolean isSuccessful() { return isSuccessful; }
public String register(){
isSuccessful = ...
}
}
and in your xhtml
....
<h:commandButton value="Submit" action="#{myBean.register()}" />
<f:ajax execute="#form" render="outtext" />
</h:commandButton>
<h:panelGroup id="outtext">
<h:outputText value="any Text" rendered="#{myBean.successful} />
</h:panelGroup>
</h:form>
I have 2 inputText components:
<h:inputText id="inputCode">
<f:ajax event="valueChange" listener="#{mbean.inputListener}"/>
</h:inputText>
<h:inputText id="inptValue">
<f:ajax event="valueChange" listener="#{mbean.inputListener}"/>
</h:inputText>
and in the managed bean:
fields:
long inputCode;
String inputText;
the listener:
public void inputListener(AjaxBehaviorEvent abe) {
UIInput uiinput = (UIInput)abe.getSource();
if(the listener is triggered by the inputText with id="inputCode") {
inputCode = (long)uiinput.getValue();
} else {
inputText = String.valueOf(uiinput.getValue());
}
}
The question is: How can I differentiate from what inputText is the listener triggered to know in what field to save the value?
I don't want to create a listener for each inputText.
I can do it by the component id, using component.id, but how can I call the listener with that parameter while it has 2 parameters: the AjaxBehaviorEvent and another would be the component id?
The id is already present on the uiinput. You could have seen this by looking at the api for UIInput So all you need to do is decide whether you need to use the id or clientId. The latter is prefixed with all id's of parent namingcontainers.
public void inputListener(AjaxBehaviorEvent abe) {
UIInput uiinput = (UIInput)abe.getSource();
if(uiinput.getId().equals("inputCode")) {
inputCode = (long)uiinput.getValue();
} else {
inputText = String.valueOf(uiinput.getValue());
}
}
Should do the trick.
I am having a JSF page that contains a modal popupPanel from Richfaces and inside this popupPanel is an extendedDataTable. Now I want to have the user selection in my bean every time the user selects a new row. At first I want to show the code then I will explain the problem.
Part of the xhtml page with the popupPanel and the extendedDatatable:
<rich:popupPanel id="kontaktPanel" modal="true" onmaskclick="#{rich:component('kontaktPanel')}.hide()">
<rich:extendedDataTable
value="#{nachfrageBean.loadedKontakte}" var="kontakt"
selection="#{nachfrageBean.selection}" id="kontaktTable">
<rich:column>
<f:facet name="header">
<h:outputText value="#{messages['tabelle.kontakt.instknz']}" />
</f:facet>
<h:outputText value="#{kontakt.instKnz}" />
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="#{messages['tabelle.kontakt.name']}" />
</f:facet>
<h:outputText value="#{kontakt.name}" />
</rich:column>
<a4j:ajax execute="kontaktTable kontaktPanel" event="selectionchange" listener="#{nachfrageBean.selectedRecord}" />
</rich:extendedDataTable>
</rich:popupPanel>
Corresponding bean with the listener and the needed members:
public class NachfrageBean {
private KontaktDTO kontakt;
private List<KontaktDTO> loadedKontakte = new ArrayList<KontaktDTO>();
/** DOCUMENT ME! */
private Collection<Object> selection;
public Collection<Object> getSelection() {
return selection;
}
public void setSelection( Collection<Object> selection ) {
this.selection = selection;
}
public List<KontaktDTO> getLoadedKontakte() {
//contacts are successfully loaded
return kontaktBusiness.getAllKontakte( );
}
public KontaktDTO getKontakt() {
return kontakt;
}
public void setKontakt( KontaktDTO kontakt ) {
this.kontakt = kontakt;
}
public void selectedRecord( AjaxBehaviorEvent event ) {
UIExtendedDataTable dataTable = ( UIExtendedDataTable )event.getComponent();
Object originalKey = dataTable.getRowKey();
for( Object selectionKey : selection ) {
dataTable.setRowKey( selectionKey );
if( dataTable.isRowAvailable() ) {
// do something with the selection
}
}
dataTable.setRowKey( originalKey );
}
}
The listener gets called successfully when the user selects a row in the datatable, but the selection is null, so I am getting a NPE. And when I remove the popupPanel and have my extendedDatatable directly in my page, then it works fine. I am always printing out the request parameters and I can see that there are two missing parameters when I have the datatable inside the pupupPanel. These request parameters are:
mainForm:kontaktTable:wi =
mainForm:kontaktTable:si = 3,3|3||x
So outside the popup the selection from the kontaktTable gets submitted but inside the popupPanel not. Does anyone know whats wrong here?
I just found a solution here .
By default the rich:popupPanel will be attached to the body and not to the form. Adding domElementAttachment="form" to the popupPanel just did it.
guys I need to update another selectOneMenu when the User selects one option of combo_pedido_tipoplm selectOneMenu. If the user selects the "Chose One" option it needs to clear the second one.
I've tried everything but I cant call my actionListener after I've selected the Option "Chose one" (Selecione) from my h:selectOneMenu.
XHTML
<h:selectOneMenu id="combo_pedido_tipoplm" value="#mBeanManterPedido.tipoPlacaMaeFiltro}" required="true" disabled="#{!mBeanManterPedido.pedidoValido or mBeanManterPedido.clonado}">
<f:selectItem itemLabel="#{msgTemplate.lblSelecione}" />
<f:selectItems value="#{mBeanManterPedido.selectItemsTipoPlacaMae}" />
<p:ajax event="change" listener="#{mBeanManterPedido.tipoPlacaMaeChange}" process="#this"/>
</h:selectOneMenu>
MBean
private TipoPlacaMae tipoPlacaMaeFiltro;
public void popularTipoPlacaMae() {
this.selectItemsTipoPlacaMae = new ArrayList<SelectItem>();
for (TipoPlacaMae tipoplaca : TipoPlacaMae.values()) {
this.selectItemsTipoPlacaMae.add(new SelectItem(tipoplaca, tipoplaca.getNome()));
}
UtilsCommon.orderByLabel(selectItemsTipoPlacaMae);
}
public void tipoPlacaMaeChange(AjaxBehaviorEvent e) {
// deseleciona a PlacaMae atualmente selecionada.
pedido.setPlacaMae(null);
limparDadosPedido();
popularPlacaMae();
}
if I select the option "Chose one" I got a validation error because this selectOneMenu is requeried and my setter for tipoPlacaMaeFiltro is not called.
<?xml version='1.0' encoding='UTF-8'?>
{"validationFailed":true}
What can I do about it ?
For those that have the same doubt.
You need to put the immediate="true" in your ajax request.
<h:selectOneMenu id="id"
value="#{mbean.value}" required="#{mbean.required}"
converter="#{mbean.converter}">
<f:selectItem itemLabel="Chose one" />
<f:selectItems value="#{mbean.selectItems}" />
<f:ajax event="valueChange" listener="#{mbean.onchange}"
render="second_combo"
immediate="true">
</f:ajax>
</h:selectOneMenu>
After that in the ManagedBean you need to implements but handle differently the listener
public void onchange(AjaxBehaviorEvent e) {
YourClass o = getSelectedValue(e);
}
private YourClass getSelectedValue(AjaxBehaviorEvent e)
{
if (e != null)
{
UISelectOne select = (UISelectOne) e.getSource();
if (select.getSubmittedValue() == null ||
select.getSubmittedValue().toString().isEmpty()) {
return null;
}
else {
String id = select
.getSubmittedValue().toString();
return ObjectThatImplementsConverterInterface.getAsObject(FacesContext.getCurrentInstance(), select, id);
}
}
return null;
}
Unfortunally you must handle that way because if you don't do the user can selects "Chose One" and the mbean.value will be OK (null) after that the second selection in the same SelectOneMenu will trigger with the previous selected value (null). I don't know if it happens with everybody or just me.
Bye.
The problem is, that if a property is changed during an f:ajax request and a binded panelGroup should be newly created depending on that changed value, the old value is used.
This code will explain the problem.
Here is the backingbean TestBean:
public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
}
public String getName(){
return first+" "+last;
}
public void setDynamicPanel(HtmlPanelGroup panel){ }
public HtmlPanelGroup getDynamicPanel(){
Application app = FacesContext.getCurrentInstance().getApplication();
HtmlPanelGroup component = (HtmlPanelGroup)app.createComponent(HtmlPanelGroup.COMPONENT_TYPE);
HtmlOutputLabel label1 = (HtmlOutputLabel)app.createComponent(HtmlOutputLabel.COMPONENT_TYPE);
label1.setValue(" --> "+getFirst()+" "+getLast());
component.getChildren().add(label1);
return component;
}
and now the jsf/facelet code:
<h:form id="form">
<h:panelGrid columns="1">
<h:inputText id="first" value="#{testBean.first}" />
<h:inputText id="last" value="#{testBean.last}" />
<h:commandButton value="Show">
<f:ajax execute="first last" render="name dyn" />
</h:commandButton>
</h:panelGrid>
<h:outputText id="name" value="#{testBean.name}" />
<h:panelGroup id="dyn" binding="#{testBean.dynamicPanel}" />
</h:form>
After the page was initially loaded the outputText and panelGroup shows both "null" as first and last. But after the button is pressed, the outputText is updated well, but the the panelgroup shows again only "null". This is due to the problem, that the "binded method" dynamicPanel is executed before the update of the first and last properties.
how can workaround this behaviour or what is wrong with my code?
If you add the attribute immediate="true" to your input elements, the values will be applied during the "Apply Request Values" phase, and hence be present before your action executes. You may or may not need the immediate attribute set to true on the commandButton as well.