Selection of extendedDataTable inside popupPanel not in Ajax Request Parameter - ajax

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.

Related

p:calendar AJAX updates only the second time

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

How can I use ajax to submit h:selectOneRadio?

I'm having a problem getting things to work the way I think they should. I have a dataTable that I'm building from a list of benefits objects. Each of those objects can have one and only one type: group, account, or parent. I want to refresh the list when a radio button is selected. When the page loads, the group objects are displayed and the group radio button is pre-selected. If the user clicks the account radio button, I'm using Ajax to refresh the list, this time presenting Account objects. Here's the stripped down code:
XHTML:
<!-- Radio button to subset records -->
<h:selectOneRadio
id="varButtons"
value="#{benefitUI.buttonValue}"
styleClass="radio">
<f:selectItem
itemLabel="Group"
itemValue="G" />
<f:selectItem
itemLabel="Account"
itemValue="A" />
<f:selectItem
itemLabel="Parent"
itemValue="P" />
<p:ajax event="click" update="benList" process="#this" />
</h:selectOneRadio>
<p:dataTable
id="benList"
var="ben"
value="#{benefitUI.filteredBenefitList}"
rowIndexVar="vbRowIndex"
rowClasses="panel-grid-row-odd, panel-grid-row-even"
styleClass="mimic-datatable"
<p:column headerText="From" style="text-align:center;">
<h:outputText value="#{ben.beginDate}"/>
</p:column>
<p:column headerText="To" style="text-align:center;">
<h:outputText value="#{ben.endDate}"/>
</p:column>
</p:dataTable>
Java for BenefitUI:
#PostConstruct
public void init() {
/* Code that creates my unfiltered list removed for brevity. */
/** benefitList is the name of the unfiltered list **/
// Pre-select group on page load
setButtonValue("G");
}
public List<Benefit> getFilteredBenefitList() {
String filter = getButtonValue();
List<Benefit> filteredList = new ArrayList<Benefit>();
for (Benefit vb : benefitList) {
// The below code is working just fine, when filter is not blank
if ((filter.equals("G") & vb.getGroup() != null)
|| (filter.equals("A") & vb.getAccount() != null)
|| (filter.equals("P") & vb.getParent() != null)) {
filteredList.add(vb);
}
}
return filteredList;
}
public void setButtonValue(String bValue) {
this.buttonValue = bValue;
}
public String getButtonValue() {
return this.buttonValue();
}
The page loads just fine, displaying the group benefits. But when I click the Account button, an empty string is passed to the setButtonValue method, so when the filtered list is built, no records are included, and the page displays an empty list. What am I doing wrong that the itemValue isn't being sent to setButtonValue? Secondarily, why are the setButtonValue and the getFilteredBenefitList methods both being called four times?
I'm sure there's a keyword or something I'm missing, either on the Ajax line or in the selectItem, but I have no idea what it might be.

Primefaces how to toggle a dashboard widget/panel visibility using ajax?

I have a dashboard with a considerable number of widgets / panels which are working just fine.
I'm looking for a way to toggle the visibility of a specific one using a commandButton ction listener without having to refresh the page, i.e. via AJAX.
<p:dashboard id="board" model="#{dashboardBean.model}">
<!-- iteration code begins -->
<p:panel id="#{wdgt.code}" header="#{wdgt.title}">
<h:outputText value="One of the dozens of widgets" />
</p:panel>
<!-- iteration code ends -->
<p:panel id="staticWdgtId" header="Static Widget Initially Invisible" visible="false">
Some static content
</p:panel>
</p:dashboard>
Then in the backing bean, at some point this action needs to be fired via a commandButton or an actionListener...
public void showTheWidget() {
DashboardColumn dbc = this.model.getColumn(1);
dbc.getWidget(2); // does not get a widget object with a visibility attribute :((
// so that I could manipulate such as dbc.getWidget(2).setVisible(true);
}
Any ideas?
STATIC APPROACH
You can associate the panel with a boolean.
Panel
<p:panel id="staticWdgtId" header="Static Widget Initially Invisible"
visible="#{bean.panelShow}">
Some static content
</p:panel>
Button
<p:commandButton actionListener="#{bean.actionListener()}"
value="Button"
update=":staticWdgtId" />
Bean
public void actionListener() {
setShowPanel(true);
}
DYNAMIC APPROACH
Render all the panel with display: none
Dashboard
<p:dashboard id="board" model="#{dashboardBean.model}">
<p:panel id="#{wdgt.code}" header="#{wdgt.title}" style="display: none">
<h:outputText value="One of the dozens of widgets" />
</p:panel>
</p:dashboard>
remoteCommand
<p:remoteCommand name="panelsToShow"
actionListener="#{bean.panelsToShowAction()}"
oncomplete="handleComplete(xhr, status, args)" />
bean.panelsToShowAction() you need Gson
public void panelsToShowAction() {
List<String> panels = new ArrayList<String>();
//iterate over the panels you want to show, and put #{wdgt.code} which is the id of the panel
panels.add("Code1");//id
panels.add("Code2");//id
RequestContext requestContext = RequestContext.getCurrentInstance();
requestContext.addCallbackParam("panels", new Gson().toJson(panels));
}
JS
$(document).ready(function() {
panelsToShow();
})
function handleComplete(xhr, status, args) {
var panels = eval('(' + args.panels + ')');
for (var i = 0, len = panels.length; i < len; i++) {
$('#'+panels[i]).show();
}
}

How to use f:selectItem properly with JSF2?

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.

JSF 2 f:ajax lifecycle problem

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.

Resources