I've added OmniFaces to my Primefaces application primarily for being able to update a single row of a dataTable. I'm calling Ajax.updateColumn(dataTable, 1) on push event, but nothing gets updated. Eg. one of my cells is like this
<p:column style="width:40px;text-align: center;"
toggleable="false" styleClass="smallPadding unmarkable">
<f:facet name="header">
<p:commandLink styleClass="ui-icon ui-icon-car"
style="display: inline-flex;" id="carIcon" />
</f:facet>
<p:tooltip for="carIcon" value="Anzahl freie Fahrzeuge" />
<h:outputText
value="#{editLoad.getAmountOfUnusedOrderPositions(order)}" />
<h:outputText value="/#{order.orderPositions.size()}" />
</p:column>
I've debugged and #{editLoad.getAmountOfUnusedOrderPositions(order))} returns 0, but the wrong value (8) is displayed after the update.
From the Ajax#updateColumn() javadoc:
public static void updateColumn(UIData table, int index)
...
Note that the to-be-updated direct child of UIColumn must be a fullworthy JSF UI component which renders a concrete HTML element to the output, so that JS/ajax can update it. So if you have due to design restrictions for example a <h:panelGroup rendered="..."> without an ID, then you should give it an ID. This way it will render a <span id="..."> which is updateable by JS/ajax.
Your <h:outputText> of interest doesn't have a id. Give it one.
<h:outputText id="amountOfUnusedOrderPositions"
value="#{editLoad.getAmountOfUnusedOrderPositions(order)}" />
Related
I have a page where I ask the user to input a value into a inputText box. Based on the entered value I create a datetable with information from my database. One of the columns in the datatable is a selectOneRadio therefore each row has its own radio button. The user should then be able to select one of the radio buttons and then click a commandbutton (which is the footer of the datatable) that will obtain which row is selected based on which radio button is selected. The problem that I am having is upon the button click the backing bean method isn't being called. This issue only happens when i create the table after going to the page. if i hard code a value to cause the datatable to exist at the creation of the page this problem does not happen. I'm not completely sure but I believe this problem is happening because the datatable rendered is initially set to false and for some reason this is effecting either the binding or the valueChangeListener some how.
This is the jsf
<h:panelGrid columns="3">
<h:outputLabel for="searchByContrId" value="Company Code: " />
<h:inputText id="searchByContrId" value="#{applContAdminB.searchContrId}">
</h:inputText>
<h:commandButton type="submit" value="Search" id="submitSearch" action="#{applContAdminB.getEmployeesByContrId}" />
</h:panelGrid>
<br />
<h:outputText rendered="#{applContAdminB.contrIdEntered}" value="Current Administrator: " />
<h:outputText value="#{applContAdminB.adminName}" />
<h:dataTable id="empTable" var="loc" rendered="#{applContAdminB.contrIdEntered}" value="#{applContAdminB.employeesListModel}" binding="#{applContAdminB.htmlDataTable}">
<h:column>
<h:selectOneRadio onclick="updateRadioButtons(this);" valueChangeListener="#{applContAdminB.setSelectedRow}">
<f:selectItem itemValue="null" itemLabel="" />
</h:selectOneRadio>
</h:column>
<h:column>
<f:facet name="header">Employee Name</f:facet>
<h:outputText value="#{loc.empName}" />
</h:column>
<h:column>
<f:facet name="header">Employee Email</f:facet>
<h:outputText value="#{loc.empEmail}" />
</h:column>
<h:column>
<f:facet name="header">Status</f:facet>
<h:outputText value="#{loc.userStatus}" />
</h:column>
<f:facet name="footer">
<h:panelGrid columns="2">
<h:commandButton type="submit" id="transferRights-submit" value="Transfer Rights" action="#{applContAdminB.adjustAdminUser}" />
</h:panelGrid>
</facet>
</h:dataTable>
you answered your own question. this is a weakness in using rendered with ajax. i had a similar issue with a navigation widget i had that toggled the attribute that rendered was bound to via ajax. no manner of magic i could muster would get the invisible panel to render while hiding the panel that was initially rendered. you might try just hiding the div via javascript and when your ajax returns twiddle the "display" attribute of the div(s) accordingly. that's how i solved it. it's unfortunate, but i could not find an alternate solution that was desirable. – him
I have the following inside a richfaces modalpanel:
<ui:repeat id="al11" var="albumslistvalue1" value="#{AlbumDetailBean.getAlbumImagesList()}"
varStatus="albumslistvalue1Index">
<rich:modalPanel id="panel#{albumslistvalue1Index}" width="850" height="560">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="Fotos"/>
</h:panelGroup>
</f:facet>
<f:facet name="controls">
<h:panelGroup>
<h:graphicImage value="/img/modal/close.png" styleClass="hidelink" id="hidelink"/>
<rich:componentControl for="panel" attachTo="hidelink" operation="hide"
event="onclick" />
</h:panelGroup>
</f:facet>
<!-- content-->
<center>
<h:graphicImage value="img/cart/prior16.png" />
<h:graphicImage value="albums/#{albumslistvalue1.albumImageId}/med_#{albumslistvalue1.albumimagename}"/>
<h:graphicImage value="img/cart/next16.png" />
<h:commandLink id="comp" action="#{AlbumDetailBean.getCartAlbums()}">
<div>
<h:outputText value="Comprar" />
<f:param name="albumproductid" value="#{albumslistvalue1.id}" />
</div>
</h:commandLink>
</center>
</rich:modalPanel>
<h:outputLink value="#" id="link">
<!-- Show Modal Panel -->
<h:graphicImage id="image" url="albums/#{albumslistvalue1.albumImageId}/mini_#{albumslistvalue1.albumimagename}"
width="100px" height="auto" />
<rich:componentControl for="panel#{albumslistvalue1Index}" attachTo="link"
operation="show" event="onclick" />
</h:outputLink>
</ui:repeat>
and getCartAlbums() method:
public List getCartAlbums() {
boolean status = false;
AlbumImpl bean1 = new AlbumImpl();
String productidval = ((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()).getParameter("albumproductid");
AlbumDetailBean albums = (AlbumDetailBean) bean1.bo_getAlbumImageDetails(productidval);
if(albums != null) {
cartAlbumDetails.add(albums);
setId(albums.getId());
setAlbumname(albums.getAlbumname());
setSchoolId(albums.getSchoolId());
setAlbumImageId(albums.getAlbumImageId());
setAlbumimagename(albums.getAlbumimagename());
// setAlbumimage(albums.getAlbumimage());
setListPrice(albums.getListPrice());
setAvailableQty(albums.getAvailableQty());
setTotalAmount(albums.getTotalAmount());
setProductcode(albums.getProductcode());
setListpricevalue(albums.getListpricevalue());
setProductsize(albums.getProductsize());
setQtyvalue(albums.getQtyvalue());
setTotalpricevalue(albums.getTotalpricevalue());
setProductid(albums.getProductid());
setShipPrice(albums.getShipPrice());
}
return cartAlbumDetails;
}
I'm using someone else's code, so i didn't write the getCartAlbums() method, but it basically add the select image to the cart, it's working, the images are added to the cart correctly, but the modalpanel still closes
I think you're using JSF 1/RF3? getCartAlbums() is returning a list, is this right? My JSF 1 knowledge is from the distant past but it doesn't look right.
However, the problem is that the h:commandLink is doing a full page submit, a POST request which reloads the page with the results of the postback (the response to the POST request). So after the button is pushed you see the screen redraw and what you're seeing is the page in the same state (albeit with updated values) as it was in when you first loaded it, which is without a modalPanel.
To remedy the problem you want to use a4j:commandLink to perform an ajax partial submit. I'm not sure if RF3 has execute= and render= attributes on the a4j:commandLink component or whether you have to use a4j:support as a child component, but I'm sure you can find out. You use execute= to specify which components values are submitted in the body of the ajax POST request, and render= to specify which components are updated after the postback is received.
I want to submit a data table on a button click, but that action is not called on the first click. Here is my code:
<h:panelGrid id="addToThisDepartmentPanel">
<h:outputText value="#{messageDataBean.message}" rendered="#{messageDataBean.isSuccess eq false}" style="color:red" id="addToThisDepartmentMessage"/>
<h:form>
<h:dataTable value="#{systemResultViewUtil.systemUserDetailDataBeansList}" var="departmentdetail" id="addToThisDepartmentDataTable" rendered="#{systemResultViewUtil.systemUserDetailDataBeansList.size() gt 0}">
<h:column>
<f:facet name="header">
Name
</f:facet>
<h:outputText value="#{departmentdetail.name}" style="text-align: left;padding-right: 120px" />
</h:column>
<h:column>
<f:facet name="header">
Current Department
</f:facet>
<h:outputText value="#{departmentdetail.depName}" style="text-align: left;padding-right: 120px" />
</h:column>
<h:column>
<f:facet name="header">
Add To This
</f:facet>
<h:selectBooleanCheckbox value="#{departmentdetail.cheked}" style="text-align: left;padding-right: 120px"/>
</h:column>
</h:dataTable>
<a4j:commandButton oncomplete="if(#{messageDataBean.isSuccess eq true}){ closeAddToThisDepartmentDialog()}" value="Add TO This Department" action="#{departmentServiceBean.addEmployeeToThisDepartment}" id="addToThisDepartmentButton"
render=":addToThisDepartmentMessage :message" execute=":addToThisDepartmentDataTable" />
</h:form>
</h:panelGrid>
The problem is that on the second click my <a4j:commandButton> action is called. But it is not called on the first click.
Any ideas?
This problem is known as JSF spec issue 790. If you ajax-render some content which in turn contains a <h:form>, then its view state will get lost, which causes that the 1st action inside that form won't invoke anything. On the ajax response of the first action, the form will get new view state and thus any subsequent actions will succeed.
This is scheduled to be fixed for the upcoming JSF 2.2. But right now with JSF 2.0/2.1 you have to introduce a workaround. You first need to give the <h:form> a fixed ID which is yourFormId in the below example:
<h:panelGrid id="addToThisDepartmentPanel">
...
<h:form id="yourFormId">
...
Then you need to reference it in the render attribute as well:
<f:ajax ... render=":addToThisDepartmentPanel :yourFormId" />
The same story applies to <a4j:xxx> components.
<a4j:commandButton ... render=":addToThisDepartmentPanel :yourFormId" />
See also:
h:commandButton/h:commandLink does not work on first click, works only on second click
Communication in JSF 2.0 - Ajax rendering of content which contains another form
I have a composite displayed inside a dialog. I have an edit button that get the current bean #SessionScoped (item in a data table) and then update the UI. My app is very similar to a simple CRUD app like http://balusc.blogspot.com/2010/06/benefits-and-pitfalls-of-viewscoped.html.
The problem is that the UI is updated correctly when using <h:outputText/> but not when using a form element.
<h:inputTextarea value="#{cc.attrs.managedBean.assertionStatement}" />
<h:inputText value="#{cc.attrs.managedBean.assertionStatement}" />
<h:outputText value="#{cc.attrs.managedBean.assertionStatement}"/>
The UI shows an empty textarea and input but the outputText renders the correct value. The getAssertionStatement() is called 3 times which seems to be the correct behavior.
When I close the dialog and reopen it, everything (form element) is populated.
The dialog call (ag namespace is for composite component):
<p:dialog widgetVar="DataValueRuleDialog" modal="true" height="600" width="800">
<p:outputPanel id="DataValueRulePanel">
<ag:DataValueAssertion managedBean="#{dataValueAssertionController}" id="DataValueComposite" />
</p:outputPanel>
</p:dialog>
The composite that calls another composite:
<h:form id="DataValueForm">
<ag:assertionMetadataComponent
managedBean="#{cc.attrs.managedBean.dataValueAssertionBean.assertionMetadataBean}"
assertionStatementRows="5" />
<p:dataTable value="#{cc.attrs.managedBean.model}" var="item">
<p:column>
<f:facet name="header">Assertion Statement</f:facet>
<h:outputText rendered="#{item.profileBean.profileLocation == cc.attrs.managedBean.selectedComformanceProfile.name}" value="#{item.assertionMetadataBean.assertionStatement}" />
</p:column>
<p:column>
<p:commandButton rendered="#{item.profileBean.profileLocation == cc.attrs.managedBean.selectedComformanceProfile.name}" value="edit" immediate="true"
actionListener="#{cc.attrs.managedBean.editDataValueAssertion}" update=":DataValueComposite:DataValueForm">
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
When I remove the immediate=true the form is validated and since one of the required field (supposed to be populated) is missing, I got a validation error. This is why I have immediate=true but it should be necessary since all the items in the data table should be valid.
I have a JSF datatable with a bunch of rows, with each row having a selectOneMenu inside of it like this:
<h:form
<h:dataTable id="myTable"
binding="#{myBean.dataTable}"
value="#{myBean.dataTableRows}" var="row"
first="0" rows="0" dir="LTR" frame="hsides" rules="all">
<h:column>
<f:facet name="header">
<h:outputText value="Sample Name" />
</f:facet>
<h:outputText value="#{row.sampleName}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Role" />
</f:facet>
<h:selectOneMenu value="#{row.role}"
id="roleInput">
<f:selectItems value="#{myBean.allRoles}" />
</h:selectOneMenu>
</h:column>
</h:dataTable>
<h:commandButton value="Save" action="#{myBean.save}" />
</h:form>
However, I can't seem to figure out how get the selected role out of each row in the save method. In other words, I want to save each row's value. I saw this article, which explains how to save an input text box:
http://balusc.blogspot.com/2006/06/using-datatables.html#EditableDatatable
but it doesn't seem to apply to the h:selectOneMenu case. Does anyone have any example code that does this?
Thanks!
I see your table has binding to your bean. In your bean you can use the getDataTable() method and access it. Java doc says:
public Object getRowData()
Return the data object representing the data for the currently selected row index, if any.
So if you do your code like:
List<String> selectedRowData = (List<String>) getDataTable().getRowData()
You can then access all the fields the user has chosen. Im using this in my own project and its working. The only difference is that Im casting to my own type instead of List<String>
There are no obvious errors in the form - if your save method is not being invoked, try adding a messages tag to your form to help track down the source of the problem. It would help if you posted a sample bean that reproduces the problem and state the JSF implementation and version you are using.