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...
Related
I was able to see data in the datatable before adding the lazy attribute. After I added the lazy attribute, the datatable is empty, because my debug points were never reached which are inside the load method of LazyDataModel. In other words load method is not called, I see the control until this.searchResults in my search()
I just get my results from web services (which work just fine) I have looked at most of the links here and here. I made sure the lazy attribute and setRowCount are set. May be someone can help me out to figure out the problem. I am using PrimeFaces 6.0, CDI, JSF 2.2, Deltaspike 1.7.2
Here is my JSF
// other input form fields
<p:panel style="border-style : none;" styleClass="panelClass">
<h:panelGrid columns="2">
<!-- <h:commandButton action="#{search.search}" value="Search" styleClass="button_small_white" /> -->
<p:commandButton action="#{search.search}" ajax="true" update=":mainform:searchResultTable" value="Search" styleClass="button_small_white" />
<h:commandButton action="#{search.clear}" value="Clear" styleClass="button_small_white" />
</h:panelGrid>
</p:panel>
<br /><p:dataTable value="#{search.searchResults}" var="rec"
rowKey="rec.numTxt"
paginator="true" rows="10"
paginatorTemplate=" Display {RowsPerPageDropdown} Records {FirstPageLink}
{PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} "
rowsPerPageTemplate="10,25,50,100"
paginatorPosition="top"
rendered="#{not empty search.searchResults}"
id="searchResultTable"
widgetVar="searchTable"
lazy="true"
summary="RE Search Results are shown below">
<p:ajax event="page" listener="#{search.search}" update=":mainform:searchResultTable" />
<p:column headerText="">
<p:selectBooleanCheckbox value="#{rec.select}" />
</p:column>
...
</p:dataTable>
Controller
#Named("search")
#Stateful
#GroupedConversationScoped
#ConversationGroup(SearchGrp.class)
public class ReSearchController extends BaseWebServicesSearchController<ReSearchSummary>
implements ReGrp, ReSearchControllerLocal {
#Inject
private GroupedConversation conversation;
#Inject
private WindowContext windowContext;
private LazyDataModel<ReSearchSummary> searchResults;
...
#PostConstruct
#Override
public void init() {
// code for initializing my web services
search();
}
#Override
public String search(){
this.searchResults = new LazyDataModel<ReSearchSummary>() {
private static final long serialVersionUID = 4168363870903585956L;
#Override
public List<ReSearchSummary> load(int first, int pageSize, String sortField, SortOrder sortOrder,
Map<String, Object> filters) {
List<ReSearchSummary> resultsList = null;
resultsList = search(first, pageSize);
// rowCount
setRowCount(getResultCount());
// I do not need sorting oor filters os did not use them
return resultsList;
}
};
searchResults.setRowCount(getResultCount());
return "/cr-re-search.xhtml?faces-redirect=true";
}
#Override
public ArrayList<ReSearchSummary> search(int first, int pageSize){
// this is my webservice call, this works fine if I call it indepedently
// criteria gets the form inputs
return doSearch(criteria.getForm(), pageSize, first);
}
...
}
Update: Converted h:commandButton to p:commandButton for the search button
<p:commandButton action="#{search.search}" ajax="true" update=":mainform:searchResultTable" value="Search" styleClass="button_small_white" />
And added p:ajax inside p:dataTable
<p:ajax event="page" listener="#{search.search}" update=":mainform:searchResultTable" />
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.
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.
In my application I am using ViewScoped Bean and it does not show selected row when a row is selected in primefaces datatable. But if I changed the Bean to a SessionScoped Bean then it shows the selected row perfectly.
my code is like below.
<h:form id="form">
<p:growl id="msgs" showDetail="true" />
<p:dataTable var="pMData" rowIndexVar="rowIndex" value="# {managedBean.dataModel}" selectionMode="single" paginator="true" rows="100"
widgetVar="pMTable" emptyMessage="No Records Found." filteredValue="#{managedBean.filteredRecords}" selection="#{managedBean.selectedRecord}" rowKey="#{pMData.cellid}">
<p:ajax event="rowSelect" listener="#{managedBean.onRowSelect}"
update=":form:display :form:msgs" oncomplete="moreviewDialog.show()" />
<p:ajax event="rowUnselect" listener="#{managedBean.onRowUnselect}" update=":form:msgs"/>
<p:column headerText="Cell Name" filterBy="#{pMData.cellid}" filterStyle="display:none" >
<h:outputText value="#{pMData.modifiedCellID}" />
</p:column>
</p:dataTable>
<p:dialog header="History Data" widgetVar="moreviewDialog" resizable="false" id="moreviewDlg"
showEffect="fade" hideEffect="explode" modal="true">
<h:panelGrid id="display" columns="2" cellpadding="4" style="margin:0 auto;">
<p:lineChart id="category" value="# {managedBean.createCategoryModel(managedBean.selectedRecord.cellid)}" legendPosition="e"
title="NodeB Throughput(kbit/s)" minY="0" maxY="5000" style="height:300px;margin-top:20px"/>
</h:panelGrid>
</p:dialog>
</h:form>
and my managedBean CDI is like this.
#Named(value = "managedBean")
#ViewScoped
public class ManagedBean implements Serializable {
public void setSelectedRecord(PMData selectedRecord1){
this.selectedRecord=selectedRecord1;
}
public PMData getSelectedRecord(){
return selectedRecord;
}
public void onRowSelect(SelectEvent event) {
FacesMessage msg = new FacesMessage("NodeB Selected", String.valueOf(((PMData) event.getObject()).getCellid()));
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onRowUnselect(UnselectEvent event) {
FacesMessage msg = new FacesMessage("Row Unselected",((PMData) event.getObject()).getCellid());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public PMDataModel getDataModel() {
return dataModel;
}
public CartesianChartModel createCategoryModel(String key) { .....}
public List<PMData> getFilteredRecords() {
return filteredRecords;
}
public void setFilteredRecords(List<PMData> filteredRecords) {
// System.out.println("came ");
this.filteredRecords = filteredRecords;
}
}
and PMData and PMDataModel classes are working normally. Can someone help me to select the row while still using viewscoped bean.
I think I found the answer. the error is with the dialogbox. I put dynamic=true in dialogbox. Now working perfectly.
I'm unable to get the tabChange event to fire when the first form (id="form1") inputText doesn't have a value. When I supply a value in the inputText the tabChange event will fire. With that said the real question would be how to restructure the below so that the onChange will fire when the first tab's inputText if empty. Each of my tab's have different forms since they each have data entry and processing that is specific to each tab.
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<p:tabView>
<p:ajax event="tabChange" listener="#{tabBean.onTabChange}"/>
<p:tab title="Tab I">
<h:form id="form1">
<p:inputText value="#{tabBean.inText}" required="true" requiredMessage="Required Field"/>
<p:commandButton value="test" actionListener="#{tabBean.submit}"/>
</h:form>
</p:tab>
<p:tab title="Tab II">
<h:form id="form2">
tab 2 content
</h:form>
</p:tab>
</p:tabView>
</h:body>
</html>
//Bean
public class TabBean extends BaseSessionBean{
private String inText;
public void onTabChange(TabChangeEvent event) {
FacesMessage msg = new FacesMessage("Tab Changed", "Active Tab: " + event.getTab().getTitle());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void submit(ActionEvent actionEvent){
System.out.println("form submitted");
}
public String getInText() {
return inText;
}
public void setInText(String inText) {
this.inText = inText;
}
}
one workaround: (remove required validation)
<p:inputText value="#{adminBean.registerationLocation}">
<p:ajax event="blur"/>
</p:inputText>
Try replacing TabChangeEvent with AjaxBehaviorEvent
javax.faces.event.AjaxBehaviorEvent