This question already has answers here:
How to dynamically add and remove a tab in p:tabView component
(2 answers)
Closed 7 years ago.
I am programmatically add a new tab whenever a menu item is clicked. I have googled for all the questions on dynamic Tab creation and found a lot of unanswered queries. So my question is, is it possible to create tabs dynamically? Below is the code I am working on for the past week and not a tab in sight..
I am using Primefaces 5.0, JSF 2.2 Mojarra
Dynamic menu -
DefaultMenuItem windowItem = new DefaultMenuItem(node);
windowItem.setCommand("#{windowContainer.add}");
windowItem.setImmediate(true);
WindowContainer Backing Bean
#ManagedBean
#ViewScoped
public class WindowContainer implements Serializable {
private List<Window> windows;
#PostConstruct
public void init() {
windows = new ArrayList<Window>();
windows.add(new Window("window"+windows.size(),"first tab"));
}
public void add() {
windows.add(new Window("window" + windows.size(), "some content"));
RequestContext req = RequestContext.getCurrentInstance();
req.update("WindowContainer");
}
public void remove(Window window) {
windows.remove(window);
}
public List<Window> getWindows() {
return windows;
}
public void setWindows(ArrayList<Window> windows) {
this.windows = windows;
}
Windows is simple tab with only outputtext .
The View
<p:tabView id= "WindowContainer" value="#{windowContainer.windows}" var="window">
<p:tab title="#{window.title}">
<p>#{tab.content}</p>
<p:commandButton value="Close" action="#{windowContainer.remove(window)}" />
</p:tab>
</p:tabView>
<p:menu>
<p:submenu label="Ajax">
<p:menuitem value="Add Tab" actionListener="#{menuView.addTab}" update="WindowContainer" />
</p:menu>
Try like this update="WindowContainer" .Inside quotes give tabview id.
Related
This question already has answers here:
Can I update a JSF component from a JSF backing bean method?
(5 answers)
Closed 3 years ago.
I'm new to PrimeFaces (and JSF too) and I'm trying to update dialog message based on retrieved data.
View looks like:
<p:dialog id="userDialog" header="Confirmation" widgetVar="userDialog" dynamic="true" modal="true" closable="fasle" width="680px" resizable="false">
<h:form>
<b>Email address #{userListView.email}</b> is already registered with the following user <b>#{userListView.firstName}</b> <b>#{userListView.lasttName}</b>:
<b>Please confirm that you would like to proceed with adding an additional account for this User.</b><br />
<hr />
<div class="ui-confirm-dialog-footer">
<p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="pi pi-check" onclick="PF('userDialog').hide()" />
<p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="pi pi-times" onclick="PF('userDialog').hide()" />
</div>
</h:form>
And controller looks like:
#ManagedBean(name = "userListView")
#ViewScoped
public class UserListView extends DataTableListView implements Serializable {
.....some other code...
public String getFirstName() {
String firstName = "";
List<UserMembership> membershipList = getMembershipList();
if (!membershipList.isEmpty()) {
UserMembership membership = membershipList.get(0);
firstName = membership.getUser().getFirstName();
}
return firstName;
}
public String getLasttName() {
String lastName = "";
List<UserMembership> membershipList = getMembershipList();
if (!membershipList.isEmpty()) {
UserMembership membership = membershipList.get(0);
lastName = membership.getUser().getLastName();
}
return lastName;
}
public String getEmail() {
String email = "";
List<UserMembership> membershipList = getMembershipList();
if (!membershipList.isEmpty()) {
UserMembership membership = membershipList.get(0);
email = membership.getUser().getEmail();
}
return email;
}
....some other code...
}
and dialog box is spawned as
RequestContext.getCurrentInstance().execute("showDialog(userDialog')");
It will work fine for the first user but then when I will get that dialog box for another one it keeps data from first one not updated with current.
Also I have try to add
onHide="PF('userDialog').content.empty()"
to the dialog but that will remove whole dialog box content.
How can I destruct and refresh that dialog box with new data then?
PS.
Not sure if I need to get this done via
#PostConstruct
public void init() {}
In the case you are using Primefaces 7.0+ swap the already mentioned
RequestContext.getCurrentInstance().update("userDialog");
for
PrimeFaces.current().ajax().update("userDialog");
If I can suggest you, set some id for <h:form> and use the full client ID after, something like
PrimeFaces.current().ajax().update("userDialog:yourFormId");
BalusC already answer a similar question in this thread Can I update a JSF component from a JSF backing bean method?
In my case fix looks like
RequestContext.getCurrentInstance().update(":userDialog");
just after .execute() part.
I am using an accordion panel with three tabs.
Each tab has required fields and <p:ajax> tags for accordionPanel:
<p:ajax event="tabChange" update=":contentForm:growl"/>
<p:ajax event="tabClose" update=":contentForm:growl"/>
By default all tabs are closed. When I click to open any tab, it performs vaidation of all inputs in all tabs.
How do I skip field validation and do ajax query during open/close tab?
(I need an Ajax query to save opened tabs indexes to Bean: activeIndex="#{tabBean.activeTabs}")
I have resolved this problem. I have created saver-class:
import javax.faces.event.AjaxBehaviorEvent;
import org.primefaces.component.accordionpanel.AccordionPanel;
public class ActiveIndexSaver {
private String activeTabs = "-1,0";
public String getActiveTabs() {
return activeTabs;
}
public void setActiveTabs(String activeTabs) {
this.activeTabs = activeTabs;
}
public void saveIndexes(AjaxBehaviorEvent abe){
AccordionPanel accordion = (AccordionPanel)abe.getComponent();
activeTabs = accordion.getActiveIndex();
}
}
After that I wrote Inject of the bean above to page-bean and getter for him:
#Inject
private ActiveIndexSaver activeIndexSaver;
....
public ActiveIndexSaver getActiveIndexSaver() {
return activeIndexSaver;
}
And finally, html:
<p:accordionPanel ... activeIndex="#{tabBean.activeIndexSaver.activeTabs}">
<p:ajax event="tabChange" immediate="true" listener="#{tabBean.activeIndexSaver.saveIndexes}"/>
<p:ajax event="tabClose" immediate="true" listener="#{tabBean.activeIndexSaver.saveIndexes}"/>
......
I have a tabview on page and add tabs with javascript dynamically. At the same time add the opened tab names to a list(lstOpenedPages). But close a tab, I can't get name of this tab which is closed for delete from the list. Now I want to read remain tabs of tabview because I can find which tab is closed from the list (lstOpenedPages).
How to I get remain tabs of tabview in Javascript?
xhtml code
<p:tabView id="tw" widgetVar="tw">
<p:ajax event="tabClose" listener="#{MenuBean.onTabClose}"/>
</p:tabView>
<p:menuitem value="#{itemMenu.menuAck}"
action="#{MenuBean.OpenPage(itemMenu.pageName)}"
ajax="true"
oncomplete="handleTabViewEvent(args);"
/>
<script type="text/javascript">
function handleTabViewEvent(args) {
alert('Add tab here..');
}
</script>
bean
public void OpenPage(String pageName) {
lstOpenedPages.add(pageName);
}
public void onTabClose(TabCloseEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
TabView tw = (TabView)context.getViewRoot().findComponent("centerForm:tw");
String s = "I must delete tab here from lstOpenedPages which closed. But event does not give me tab information. It is always null. So I must be delete from javascript";
}
I have Primefaces TabView with two Tab like:
<p:tabView dynamic="true" cache="false"
onTabShow="scrollBottom(#{stanzaBean.activeIndex})"
tabChangeListener="#{messaggioBean.onTabChange}"
activeIndex="#{stanzaBean.activeIndex}" >
it works fine, except that when I change the Tab the activeIndex isn't updated on the Server and it returns always the default value.
I'm using primefaces 2.2.1.
Thank you.
Going by the PrimeFaces ShowCase example, if you give each tab an id:
<p:tabView tabChangeListener="#{indexBean.onTabChange}" >
<p:tab title="tab 0" id="tab0"></p:tab>
<p:tab title="tab 1" id="tab1" ></p:tab>
<p:tab title="tab 2" id="tab2"></p:tab>
</p:tabView>
you can get that tab id in the tabChangeListener.
public void onTabChange(TabChangeEvent event) {
System.out.println("tab id = " + event.getTab().getId());
}
Then you'll know which tab was selected.
Edit:
There is an open PrimeFaces issue 1640 TabView: Wrong activeIndex in TabChangeListener, always 0 on the problem you are having.
Edit 2:
With PrimeFaces 5.0 and up the tabChangeListener is no longer available on the tabView element but should be used via an explicit ajax tag with a tabChange event.
<p:tabView id="analysisSections" value="#{analysisBean.analysis.sections}" var="section" activeIndex="#{analysisBean.activeIndex}">
<p:ajax event="tabChange" listener="#{analysisBean.onTabChange}"/>
Also you can directly get index of tab:
public void onTabChange(TabChangeEvent event) {
activeIndex = ((TabView) event.getSource()).getIndex();
}
with all these changes, activeIndex works properly.
this worked for me:
public void onTabChange(TabChangeEvent event) {
Tab activeTab = event.getTab();
tabPanelIndex = ((TabView)event.getSource()).getChildren().indexOf(activeTab);
}
Although the question was related to PrimeFaces 2.2.1, I like to mention that in modern PrimeFaces versions (tested with version 6.2) there is no need to trigger a separate event when attribute dynamic is set to true and cache is set to false. By using this attribute combination the active index is automatically updated on the server when another tab is selected.
Facelet:
<p:tabView activeIndex="#{stanzaBean.activeIndex}"
cache="false"
dynamic="true">
Bean:
#Named
#ViewScoped
public class StanzaBean implements Serializable {
private int activeIndex;
public int getActiveIndex() {
return activeIndex;
}
/**
* Automatically called whenever a tab changes and dynamic="true"
* and cache="false".
*/
public void setActiveIndex(int activeIndex) {
this.activeIndex = activeIndex;
// do other stuff when tab changes
}
}
This question already has answers here:
How can I pass selected row to commandLink inside dataTable or ui:repeat?
(4 answers)
Closed 7 years ago.
I am using a JSF data table. One of the columns in the table is a Command button.
When this button is clicked I need to pass few parameters (like a value of the selected row) using the Expression language. This paramaters need to be passed to the JSF managed bean which can execute methods on them.
I have used the following snippet of code but the value i am getting on the JSF bean is always null.
<h:column>
<f:facet name="header">
<h:outputText value="Follow"/>
</f:facet>
<h:commandButton id="FollwDoc" action="#{usermanager.followDoctor}" value="Follow" />
<h:inputHidden id="id1" value="#{doc.doctorid}" />
</h:column>
Bean Method:
public void followDoctor() {
FacesContext context = FacesContext.getCurrentInstance();
Map requestMap = context.getExternalContext().getRequestParameterMap();
String value = (String)requestMap.get("id1");
System.out.println("Doctor Added to patient List"+ value);
}
How can I pass values to the JSF managed bean with a commandbutton?
Use DataModel#getRowData() to obtain the current row in action method.
#ManagedBean
#ViewScoped
public class Usermanager {
private List<Doctor> doctors;
private DataModel<Doctor> doctorModel;
#PostConstruct
public void init() {
doctors = getItSomehow();
doctorModel = new ListDataModel<Doctor>(doctors);
}
public void followDoctor() {
Doctor selectedDoctor = doctorModel.getRowData();
// ...
}
// ...
}
Use it in the datatable instead.
<h:dataTable value="#{usermanager.doctorModel}" var="doc">
And get rid of that h:inputHidden next to the h:commandButton in the view.
An -less elegant- alternative is to use f:setPropertyActionListener.
public class Usermanager {
private Long doctorId;
public void followDoctor() {
Doctor selectedDoctor = getItSomehowBy(doctorId);
// ...
}
// ...
}
With the following button:
<h:commandButton action="#{usermanager.followDoctor}" value="Follow">
<f:setPropertyActionListener target="#{usermanager.doctorId}" value="#{doc.doctorId}" />
</h:commandButton>
Related:
The benefits and pitfalls of #ViewScoped - Contains CRUD example using DataModel<E>.