Versions: PrimeFaces 3.5, JPA 2.1, GlassFish 4.0, Java EE 7, JSF 2.0.
Dialog normally opens and displays data for edition, but the "Update" button in this dialog is not working. Button code follows:
<p:commandButton actionListener="#{funcionarioMB.save}"
value="Alterar"
oncomplete="dlg.hide();"
update=":tblFuncionarios"
ajax="false" />
Full dialog code:
<p:dialog id="dlg"
header="Editar funcionário"
modal="true"
widgetVar="editarDialog"
closable="true"
draggable="false"
appendToBody="true"
maximizable="false"
minimizable="false"
position="center"
resizable="false"
showEffect="slide">
<p:outputPanel>
<h:form id="formAlterar">
<h:panelGrid id="infosFuncionario">
<!-- inputs -->
<p:commandButton actionListener="#{funcionarioMB.save}"
value="Alterar"
oncomplete="dlg.hide();"
update=":tblFuncionarios"
ajax="false" />
</h:panelGrid>
</h:form>
</p:outputPanel>
</p:dialog>
Update commandButton within the dataTable:
<h:form>
<p:commandButton actionListener="#{funcionarioMB.prepareEdit(funcionario.id)}"
value="alterar"
oncomplete="editarDialog.show();"
update=":formAlterar" />
</h:form>
Method save() in the managed bean:
public void save() {
Cargo cargo = this.cargoRepositorio.findById(this.cargoID);
funcionario.setCargo(cargo);
if (this.getFuncionario().getId() == null) {
this.funcionarioRepositorio.add(this.getFuncionario());
} else {
this.funcionarioRepositorio.edit(this.getFuncionario());
}
this.funcionario = new Funcionario();
this.funcionarios = null;
}
Method edit() in the repository:
public void edit(Funcionario funcionario) {
this.manager.merge(funcionario);
}
And the button for updating the entity doesn't work without ajax="false".
where is your datatable ?
just recreate/rebuild your datatable value.
in your managedbean/backing bean add this method after CRUD operation execute
public List<T> refreshDatatable(){
list=yourEJBFacade().getList();
return list
}
in your session bean
public List<T> getList(){
Query q = entityManager.createQuery("select a from YourEntityClass a");
return q.getResultList();
}
update your datatable (update=":tblFuncionarios")
for references see this question at
Primefaces datatable Reset and Reload data
Added ActionEvent actionEvent as save method's parameter and now it's working, thanks to Erick R. Ribeiro's hint in the PrimeFaces Facebook group.
Related
In an application based on jsf 2.1 and Primefaces 6.1.5, I have difficulties implementing a <p:selectCheckboxMenu
I simplified the code according to the instructions here How to create a Minimal, Complete, and Verifiable example
My code now looks quite similar to the code in the Primefaces Showcase.
Primefaces Showcase
After much analyzing, I can describe 'erratic' a bit better. When deselecting an item, the item following it is affected. The last item is not affected at all. And the first item can never be deselected. It seems like a bug in the use of indices.
Can anyone confirm this and perhaps suggest a Workaround?
Here is the xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:form id="form">
<p:panel>
<p:selectCheckboxMenu id="testSCM"
value="#{myForm.testList}"
multiple="true"
label="Choose item..."
updateLabel="true">
<f:selectItems var="s" value="#{myForm.testItems}" itemLabel="#{s}" />
</p:selectCheckboxMenu>
</p:panel>
<p:commandButton value="Submit" update="displayItems" oncomplete="PF('itemDialog').show()" style="margin-top:10px;" />
<p:dialog header="Selected Items" modal="true" showEffect="fade" hideEffect="fade" widgetVar="itemDialog" width="250">
<p:outputPanel id="displayItems">
<p:dataList value="#{myForm.statusList}" var="item" emptyMessage="No items selected">
<f:facet name="header">
Status
</f:facet>
#{item}
</p:dataList>
</p:outputPanel>
</p:dialog>
</h:form>
</ui:composition>
And this is the form:
#Named("myForm")
#SessionScoped
public class MyForm implements Serializable {
private String[] testList;
private List<String> testItems;
public String[] getTestList() {
return testList;
}
public void setTestList(String[] testList) {
this.testList = testList;
}
public List<String> getTestItems() {
return testItems;
}
public void setTestItems(List<String> testItems) {
this.testItems = testItems;
}
public void reset() {
testItems = new ArrayList<>();
testItems.add("Item1");
testItems.add("Item2");
testItems.add("Item3");
testItems.add("Item4");
testItems.add("Item5");
testItems.add("Item6");
}
}
The problem was caused by a bug in Primefaces version 6.1.5. The code works fine when downgrading to Version 6.0 or upgrading to Version 6.1.8, which is what I chose to do.
The problem is described in Primefaces issue tracker on github
Context
I have a datatable with a button that opens a dialog when clicked. That dialog shows additional data (xml content) in a p:inputTextarea
Question
Now I would like to make this p:inputTextarea editable and have the changes reflected in the object of the datatable. I wanted to add a commandbutton in the dialog to save the changes. How do I get a reference to the selected object ?
Xhtml
<h:form id="alltxform">
<p:dataTable id="tablealltx" var="transaction" value="#{transactionListModel.txList}">
<p:column>
<p:commandButton update=":alltxform:xmlDetail" oncomplete="PF('dialog').show()">
<f:setPropertyActionListener value="#{transaction}"
target="#{transactionListModel.selectedTx}" />
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog header="Detail" widgetVar="dialog">
<p:outputPanel id="xmlDetail">
<p:inputTextarea readonly="false" id="xmlviewer"
value="#{transactionListModel.selectedTx.xml}" />
</p:outputPanel>
</p:dialog>
</h:form>
Model
package model;
#Named
#SessionScoped
public class TransactionListModel implements Serializable {
private static final long serialVersionUID = 1L;
private List<TransactionVO> txList;
private TransactionVO selectedTx;
public TransactionVO getSelectedTx() {
return selectedTx;
}
public void setSelectedTx(TransactionVO selectedTx) {
this.selectedTx = selectedTx;
}
#PostConstruct
public void init() {
txList = new ArrayList<TransactionVO>();
}
public List<TransactionVO> getTxList() {
return txList;
}
public void clearList(){
txList = new ArrayList<TransactionVO>();
}
}
Button
I want to add this button to the dialog.
<p:commandButton value="OK" onclick="PF('dialog').hide();" actionListener=""/>
I read about cellEdit events, but that's not really what I need. I need a reference to my transaction object inside the dialog in order to save the changes.
Do you mean the dialog will look like -
<p:dialog header="Detail" widgetVar="dialog">
<p:outputPanel id="xmlDetail">
<p:inputTextarea readonly="false" id="xmlviewer"
value="#{transactionListModel.selectedTx.xml}" />
<p:commandButton value="OK" onclick="PF('dialog').hide();" actionListener=""/>
</p:outputPanel>
</p:dialog>
And the action will refresh the model, before refreshing the table?
And you want to access TransactionListModel.selectedTx?
Well if its in the model and accessible from the controller then just -
actionListener="#{yourController.yourAction(transactionListModel.selectedTx)}"
And Update the underlying datastructure in the yourAction method, before updating :tablealltx:tablealltx
I'm new to jsf and I'm using Primefaces 4.0 to write a tabView.
I want to do something in my Backing Bean when specific tab is clicked, so I tried this:
page:
<p:tabView effect="fade" effectDuration="normal">
<p:ajax event="tabChange" listener="#{myConsoleBean.onTabChange}" update=":rightForm"/>
<p:tab title="My">
</p:tab>
<p:tab id="statTab" title="Stat">
</p:tab>
</p:tabView>
Backing Bean:
public void onTabChange(final TabChangeEvent event) {
TabView tv = (TabView) event.getComponent();
int activeTabIndex = tv.getActiveIndex();
System.out.println(activeTabIndex);
if(activeTabIndex==1)//Stat tab clicked
{
//do something here...
}
}
Everything works till now,but the Backing Bean is slow for some reason,I want to show a Dialog which contains a progress bar while the Backing Bean is progressing:
Dialog like this:
<p:dialog id="pBarDialog" header="Progressing..." widgetVar="dlg" modal="true" height="70" resizable="false" closable="false">
<h:outputText value="Please wait, we're generating your info..." />
<p:progressBar widgetVar="pbAjax" ajax="true" value="100" styleClass="animated"> </p:progressBar>
</p:dialog>
So, how can I show the dialog when I click the "Stat" tab?
You could do something like this :
public void onTabChange(TabChangeEvent event) {
TabView tv = (TabView) event.getComponent();
int activeTabIndex = tv.getActiveIndex();
System.out.println(activeTabIndex);
if(activeTabIndex==1)//Stat tab clicked
{
//do something here...
}
if(activeTabIndex==2){
RequestContext.getCurrentInstance().execute("PF('dlg').show()"); //For Primeface 4.0
RequestContext.getCurrentInstance().execute("dlg.show()"); //Before Primeface 4.0
}
}
A solution could be to use the visible attribute on the dialog:
<p:dialog id="pBarDialog" header="Progressing..." visible="#{myConsoleBean.showDialog}"
modal="true" height="70" resizable="false" closable="false">
In your bean:
private boolean showDialog;
public void displayDialog() {
showDialog = true;
}
public boolean getShowDialog() {
return showDialog;
}
And then
if(activeTabIndex==1)//Stat tab clicked
{
myConsoleBean.displayDialog();
}
Also be sure that your ajax components updates the dialog
I think I resolved this problem.
I used p:remoteCommand after I saw this thread.
And here's my final codes:
Page:
<p:tabView effect="fade" effectDuration="normal">
<p:ajax event="tabChange" listener="#{myConsoleBean.onTabChange}" oncomplete="dlg.hide()" update=":rightForm"/>
<p:tab title="My">
</p:tab>
<p:tab id="statTab" title="Stat">
<p:remoteCommand actionListener="#{myConsoleBean.goToUrl('myStat.xhtml')}" update=":rightForm" name="showStat" global="true" onstart="dlg.show()" oncomplete="dlg.hide()"></p:remoteCommand>
</p:tab>
</p:tabView>
<p:dialog id="pBarDialog" header="Progressing..." widgetVar="dlg" modal="true" height="70" resizable="false" closable="false">
<h:outputText value="Please wait, we are generating your info..." />
<p:progressBar widgetVar="pbAjax" ajax="true" value="100" styleClass="animated">
</p:progressBar>
</p:dialog>
Bean:
public void onTabChange(TabChangeEvent event) {
TabView tv = (TabView) event.getComponent();
int activeTabIndex = tv.getActiveIndex();
if(activeTabIndex==1)
{
RequestContext.getCurrentInstance().execute("showStat()");
}
}
No matter how, thank you both,Lamq and Emil Kaminski.
I will never find that thread without your help because I type key words from your answers.
Salut :), iam a newbie in primefaces and ajax
Iam using primefaces 3.4, glassfish 3.1, jsf2.0 and ejb 3. I tried to implement primefaces showcase datatable rowediting. But when i validate the updated value into the datatable, i get the old value. This is my code :
<h:form id="form">
<p:growl id="messages" showDetail="true"/>
<p:dataTable var="item" value="#{jSFMBean.allContacts}" id="contactList" editable="true">
<p:ajax event="rowEdit" listener="#{jSFMBean.onEdit}" update="#this :form:messages" />
<p:ajax event="rowEditCancel" listener="#{jSFMBean.onCancel}" update=":form:messages" />
<p:column headerText="EMAIL" style="width:125px">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{item.email}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{item.email}" label="EMAIL"/>
</f:facet>
</p:cellEditor>
</p:column><p:column headerText="Options" style="width:50px">
<p:rowEditor />
</p:column>
</p:dataTable>
<h:outputText value="#{jSFMBean.selectedContact.displayname}" />
the methods are :
public void onEdit(RowEditEvent event) {
this.session.updateContact((Contacts) event.getObject());
FacesMessage msg = new FacesMessage("Edition contact: ", ((Contacts) event.getObject()).getDisplayname());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
(Contacts) event.getObject() always get the old value :(. It's like the getter of the datatable fireup first before ajax update to the database.
what iam i doing wrong ? thank you for your help solving this .
Currently you're editing values within the object. It looks like you still need to make a call back to your database to update the value there.
It seems that whenever you need your dataTable you are getting it from your database and that's why event.getObject() always returns the old value.So in the getter of your datatable you need to add:
if (allContacts== null){
allContacts= (List<Contacts>) yourservice.getAll(); /*this refers to the function that get the list from the database*/
}
return allContacts;
I hope that may help you.
Most probably the problem is with your backing bean. if you have used #Named annotation instead of #ManagedBean (javax.faces.bean.ManagedBean) for your backing bean, you faces this kind of problems. Simply replace
#Named (value="YourBeanName")
with
#ManagedBean (name="YourBeanName")
Active Index is not getting updated automatically. ReaD in a few posts that by placing the tabView on a form it works. Or by including <p:ajax event="tabChange"/> in the tabview it works. But nothing seems to work
xhtml
Sample 1 : automatic updates
<p:tabView id="categoryTabView" var="promoArticle" value="#{promotionDetailBean.artDTOs}" activeIndex="#{promotionDetailBean.activeTabIndex}">
<p:tab id="categoriesTab" title="#{promoArticle.categoryName}">
<p:dataTable id="promotionDetail_dataTable" var="articlePromo" value="#{promoArticle.artVO}" selection="#{promotionDetailBean.selectedArt}" rowIndexVar="rowIndex">
<p:column id="select" selectionMode="multiple" />
<p:column id="barCode">
<h:inputText id="barCodeInputTxt" value="#{articlePromo.barCode}"
styleClass="inputTextStyle" onchange="onSuggestedValueChange('categoryTabView',#{promotionDetailBean.activeTabIndex}, 'promotionDetail_dataTable',#{rowIndex},'originalCostInputTxt')" />
</p:column>
</p:dataTable>
</p:tab>
</p:tabView>
Sample 2: Updating on tabChange event
<h:form id="form">
<p:growl id="growlm" showDetail="true" />
<p:tabView id="categoryTabView" var="promoArticle" value="#{promotionDetailBean.artDTOs}" >
<p:ajax event="tabChange" listener="#{promotionDetailBean.tabChanged}" update=":growlm" />
<p:tab id="categoriesTab" title="#{promoArticle.categoryName}">
<p:dataTable id="promotionDetail_dataTable" var="articlePromo" value="#{promoArticle.artVO}" selection="#{promotionDetailBean.selectedArt}" rowIndexVar="rowIndex">
<p:column id="select" selectionMode="multiple" />
<p:column id="barCode">
<h:inputText id="barCodeInputTxt" value="#{articlePromo.barCode}"
styleClass="inputTextStyle" onchange="onSuggestedValueChange('categoryTabView',#{promotionDetailBean.activeTabIndex}, 'promotionDetail_dataTable',#{rowIndex},'originalCostInputTxt')" />
</p:column>
</p:dataTable>
</p:tab>
</p:tabView>
I need to identify the cell on "onChange " event. But the activeIndex is always 0, the initialized value. The event doesn't get call.
bean
private Integer activeTabIndex = 0;
public Integer getActiveTabIndex() {
return activeTabIndex;
}
public void setActiveTabIndex(Integer activeTabIndex) {
this.activeTabIndex = activeTabIndex;
}
bean
public void tabChanged(TabChangeEvent event){
TabView tv = (TabView) event.getComponent();
this.activeTabIndex = tv.getActiveIndex();
}
But the event is not getting trigerred. Nor getting updated automatically.
What could be the probable issues ?
Thanks,
Shikha
This works for me when the tab is not contained inside a form but every tab contains its own one:
Add a listener to tab change event to your tabView component:
<p:ajax event="tabChange" listener="#{userBean.onTabChange}" />
Getting the active index from the underlying TabView component doesn't seem to be working. However, in the event, the new selected tab is updated correctly so we can getthe index by searching in the children components of the TabView:
public void onTabChange(TabChangeEvent event)
{
TabView tabView = (TabView) event.getComponent();
activeTab = tabView.getChildren().indexOf(event.getTab());
}
I hope this works for you too
The following worked for me:
XHTML:
<p:tabView id="categoryTabView" var="promoArticle"
value="#{promotionDetailManagedBean.articuloPromocionDTOs}" dynamic="true">
<p:ajax event="tabChange" listener="#{promotionDetailManagedBean.onTabChange}" />
<p:tab> ... </p:tab>
</p:tabView>
Bean:
public final void onTabChange(final TabChangeEvent event) {
TabView tv = (TabView) event.getComponent();
this.activeTabIndex = tv.getActiveIndex();
}
For primefaces >= 5.0
please use the following code :
public final void onTabChange(TabChangeEvent event) {
TabView tv = (TabView) event.getComponent();
this.ActiveIndex = tv.getChildren().indexOf(event.getTab());
}
That only seems to work if active index is not binded to the managed bean. But this is useless for me since I want to keep a backing bean-view synchronization. I'm astonished Primefaces team has not resolved it yet (I'm working with 3.5 version). However it works if the p:tabView itself is wrapped into a h:form instead of having one of them for each tab, but this makes you change your submit context.
<p:column id="barCode">
<h:inputText id="barCodeInputTxt" value="#{articlePromo.barCode}"
styleClass="inputTextStyle" onchange="onSuggestedValueChange('categoryTabView',
#{promotionDetailBean.activeTabIndex},
'promotionDetail_dataTable',#{rowIndex},
'originalCostInputTxt')" /> **_____/>_____**
</p:column>
you have an extra />
immediate true may cause problem with p:ajax, you should use immediate true when you dont have validation or you are trying cancel operation.
public void tabChange(TabChangeEvent event){
TabView tabView = (TabView) event.getComponent();
Tab tab = (Tab) event.getTab();
String tabChangedMessage = tab.getTitle() + " changed. index=" + tabView.getActiveIndex();
System.out.println(tabChangedMessage);
FacesContext fc = FacesContext.getCurrentInstance();
fc.addMessage(null, new FacesMessage("Tab changed", tabChangedMessage));
}
<p:tabView>
<p:ajax event="tabChange" listener="#{tabChangeBean.tabChange}" update=":growlId" />
<p:tab title="tab 1">
tab1 inside
</p:tab>
<p:tab title="tab 2">
tab1 inside
</p:tab>
</p:tabView>
This works but active index is 0.
in your xhtml you are calling listener="#{promotionDetailBean.onTabChange}" but in your bean the method name is "public void tabChanged". So it cannot trigger.
I have tried an example on prime-showcase at:
in bean (TabBean):
private Integer activeTabIndex = 1;
// setter/getter
public void onTabChange(TabChangeEvent event) {
FacesMessage msg = new FacesMessage("Tab Changed", "Active Tab: " + event.getTab().getTitle());
TabView tabView = (TabView) event.getComponent();
int activeTabIndex = tabView.getActiveIndex();
System.out.println("--------" + activeTabIndex);
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> params = context.getExternalContext().getRequestParameterMap();
String activeIndexValue = params.get(tabView.getClientId(context) + "_activeIndex");
System.out.println("--------" + activeIndexValue);
context.addMessage(null, msg);
}
in xhtml (tabviewChangeListener.xhtml):
<p:tabView id="tabView" dynamic="true" activeIndex="#{tabBean.activeTabIndex}">
<p:ajax event="tabChange" listener="#{tabBean.onTabChange}" update=":form:growl"/>
<p:tab title="Godfather Part I" id="Godfather1">
The result is as expected:
At beginning the second tab is displayed. I click first tab and then third. sysout is:
--------0
--------0
--------2
--------2
i easy fix this with:
public void onSPTabChange(TabChangeEvent event)
{
TabView tabView = (TabView) event.getComponent();
currentData.setSP_Index(tabView.getChildren().indexOf(event.getTab())+1);
}
in currentdata i have property SP_Index with number of tab (first,second....)
<p:tabView id="tabView" styleClass="tabView">
<p:ajax event="tabChange" listener="#{dataAccess.onSPTabChange}" />
....
and add jquery script
<script>
$("#tabView li:nth-child(#{currentData.SP_Index})").click();
</script>
public final void onTabChange(final TabChangeEvent event) {
TabView tv = (TabView) event.getComponent();
this.activeTabIndex = tv.getIndex();
}
This worked for me...