I'm trying to rerender a second dropdown when i change the value in the first one.
But nothing happens when I click and change the value in the first drop down.
Have I missed any crucial part?
My xhtml:
<h:form>
<h:selectOneMenu value="#{adminBean.currentLeadCategory}" required="true" styleClass="formfield fpgeo" style="width:20em;margin-right:20px;">
<a4j:support event="onchange" action="#{adminBean.currentLeadCategoryChanged()}"
reRender="componentToReRender"/>
<s:selectItems value="#{leadCategories}" var="leadCategory" label="#{leadCategory.name}" noSelectionLabel="Choose Category"/>
<s:convertEntity/>
</h:selectOneMenu>
<a4j:outputPanel id="componentToReRenderWrapper">
<h:selectOneMenu id="componentToReRender" value="#{adminBean.currentCounty}"
styleClass="formfield fpgeo" style="width:20em;margin-right:20px;">
<s:selectItems value="#{adminBean.counties}" var="county" label="#{county.name}" noSelectionLabel="choose"/>
<s:convertEntity/>
</h:selectOneMenu>
<h:messages/>
</a4j:outputPanel>
</h:form>
My bean:
#AutoCreate
#Scope(ScopeType.CONVERSATION)
#Name("adminBean")
#MeasureCalls
#Restrict("#{s:hasRole('admin') or s:hasRole('sales')}")
public class AdminBean implements Serializable {
private LeadCategory currentLeadCategory;
private List<County> counties = new ArrayList<County>();
private County currentCounty;
#Factory(value = "leadCategories", autoCreate = true, scope = ScopeType.SESSION)
public List<LeadCategory> fetchLeadCategories() {
Query query = entityManager.createQuery("select l from LeadCategory l");
return query.getResultList();
}
public LeadCategory getCurrentLeadCategory() {
return currentLeadCategory;
}
public void setCurrentLeadCategory(LeadCategory currentLeadCategory) {
this.currentLeadCategory = currentLeadCategory;
}
public County getCurrentCounty() {
return currentCounty;
}
public void setCurrentCounty(County currentCounty) {
this.currentCounty = currentCounty;
}
public void currentLeadCategoryChanged() {
this.loadCountiesForCategory();
}
public List<County> getCounties() {
return counties;
}
public void setCounties(List<County> counties) {
this.counties = counties;
}
public void loadCountiesForCategory(){
if(currentLeadCategory == null){
counties = new ArrayList<County>();
}
counties = new ArrayList<County>(currentLeadCategory.getCounties());
}
}
EDIT 1:
If i check firebug i get an error:
Timestamp: 7/19/12 4:14:44 PM
Error: ReferenceError: A4J is not defined
Source File: http://localhost:8080/admin/admin.seam?cid=11
Line: 1
Ok found the problem! Major crazyness going on here. Someone has set LoadScriptStrategy
param to NONE in the web.xml. This makes that the framework.pack.js and ui.pack.js is NOT loading.
<context-param>
<param-name>org.richfaces.LoadScriptStrategy</param-name>
<param-value>NONE</param-value>
</context-param>
Found this page at docs.jboss
If you use the "NONE" strategy, you must include the following scripts
in your portlet or portal page header. If you are using JBoss Portal,
you can add this to the jboss-portlet.xml file.
Added <a4j:loadScript src="resource:///org/ajax4jsf/framework.pack.js"/>
to my header template and viola everything works like a charm.
I love my job =)
I can see clearly that your xhtml has an ending tag </a4j:outputPanel> but no starting tag: <a4j:outputPanel>
If you rearrange your tags it will work.
Related
I'm trying to update a whole page in adf when you click on a link to go to the same page with new page parameters. If I open the link in a new tab, it works fine, but opening it in the same tab doesn't update.
I have a page that just displays the parameter value from the url, a link to the same page with a different parameter value, and an output text that displays the datetime. My taskflow starts by calling RetrieveDateTime() and then goes to refrestTest.jsff. The taskflow is a region on refresh.jsf page.
public class RefreshDC {
private String dateTime;
public RefreshDC() {
super();
}
public void RetrieveDateTime() {
System.out.println("DC RETRIEVEDATETIME");
RefreshFacade rf = new RefreshFacade();
this.dateTime = rf.getDate().getDatetime();
}
public void setDateTime(String dateTime) {
this.dateTime = dateTime;
}
public String getDateTime() {
return dateTime;
}
}
The page fragment:
//refreshTest.jsff
<?xml version='1.0' encoding='UTF-8'?>
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
<af:panelGroupLayout id="pgl1" layout="vertical">
<af:outputText value="#{param.id}" id="ot1"/>
<af:goLink text="RP PDTLS" id="gl1" destination="/faces/refresh.jsf?
id=1234567890"/>
<af:outputText value="DateTime: #{bindings.dateTime.inputValue}"
shortDesc="#{bindings.dateTime.hints.tooltip}" id="ot2"
partialTriggers="gl1"/>
</af:panelGroupLayout>
</ui:composition>
The page:
//refresh.jsf
<f:view xmlns:f="http://java.sun.com/jsf/core"
xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
<af:document title="refresh.jsf" id="d1">
<af:form id="f1">
<af:region value="#{bindings.refresh1.regionModel}" id="r1"/>
</af:form>
</af:document>
</f:view>
As i said, if you open the goLink in a new tab, it will update the dateTime, however if you open it in the same tab, dateTime remains the same. (The param.id does update in both cases)
You can refresh the whole page programatically by replacing your golink by an adf button with an ActionListener calling the following java bean function :
public static void refreshPage() {
FacesContext fc = FacesContext.getCurrentInstance();
String refreshpage = fc.getViewRoot().getViewId();
ViewHandler ViewH = fc.getApplication().getViewHandler();
UIViewRoot UIV = ViewH.createView(fc, refreshpage);
UIV.setViewId(refreshpage);
fc.setViewRoot(UIV);
}
I managed to solve this using the taskflow. Basically, I made the button go to a new page with a region. This region has a taskflow that reads the url parameters and if it matches my conditions, links back to the original page with new parameters (toDocumentsPage). Otherwise, goes to a different page (searchResults).Taskflow to refresh the page
so I have an extendedDataTables as follows(Code is shortened to keep it straightforward).
<rich:extendedDataTable value="#{package.packageList}" var="o"
styleClass="listStyle" selection="#{package.selection}"
selectionMode="single">
<a4j:ajax execute="#form" event="selectionchange"
listener="#{package.selectionListener}" render=":res" />
<rich:column>
<f:facet name="header">Package ID</f:facet>
#{o.packageID}
</rich:column>
</rich:extendedDataTable>
So when the user clicks on this it outputs the details of it to another table inside the a4j:outputPanel that follows.
<a4j:outputPanel id="res">
<rich:panel header="Selected Package"
rendered="#{not empty package.selectionPackage}">
</rich:panel>
</a4j:outputPanel>
This part works. However this new detail now contains several variables and also an arrayList of objects with which I need to also be able to select. So this arrayList generates its own extendedDataTable which I need to then select and retrieve its information. This part is where it is breaking. What I have attempted so far looks as follows.
<a4j:outputPanel id="res">
<rich:panel header="Selected Package"
rendered="#{not empty package.selectionPackage}">
<rich:dataTable value="#{package.selectionPackage}"
var="extensionTable" styleClass="listStyle" selectionMode="single">
<rich:column>
<rich:extendedDataTable value="# {extensionTable.extensionList}"
var="selectedExtension" styleClass="listStyle" style="height:200px;"
selection="#{package.extensionSelection}" selectionMode="single">
<a4j:ajax execute="#form" event="selectionchange"
listener="#{package.selectionExtensionListener}" render=":extensions" />
<rich:column>
<f:facet name="header">Extension Add on list</f:facet>
#{selectedExtension.extensionName}"
</rich:column>
</rich:extendedDataTable>
</rich:column>
</rich:dataTable>
</rich:panel>
</a4j:outputPanel>
I have another a4j panel to handle the new extensions selected object. The problem is that my selectedExtensionListener is not being called. I do not know why, is what I am trying even possible. The selection is working as the rows are changing colour however the selectionExtensionListener is never being called. I have some system.out.printlnts in just to check and whereas the first listener is being called the second one is not. Forgive me if this is obvious or not even possible but I am relatively new to jsf. Any help would be greatly appreciated.
I will copy and paste my bean below to show you the backend of the code. I will exclude declaring all of my variables and populating my lists and objects etc as it will just clog up the code, if you need them just let me know and I will edit them in. (Sorry for formatting, I do not know if you can format code here?)
public class Package implements Serializable{
public void selectionListener(AjaxBehaviorEvent event) {
System.out.println("In selection listener");
UIExtendedDataTable dataTable = (UIExtendedDataTable) event.getComponent();
Object originalKey = dataTable.getRowKey();
selectionPackage.clear();
for (Object selectionKey : selection) {
dataTable.setRowKey(selectionKey);
if (dataTable.isRowAvailable()) {
selectionPackage.add((PackageClass) dataTable.getRowData());
}
}
dataTable.setRowKey(originalKey);
}
public void selectionExtensionListener(AjaxBehaviorEvent event) {
System.out.println("Testing 1");
UIExtendedDataTable dataTable = (UIExtendedDataTable) event.getComponent();
Object originalKey = dataTable.getRowKey();
selectionExtension.clear();
for (Object selectionKey : extensionSelection) {
dataTable.setRowKey(selectionKey);
if (dataTable.isRowAvailable()) {
System.out.println("Testing 2");
selectionExtension.add((ExtensionClass) dataTable.getRowData());
}
}
dataTable.setRowKey(originalKey);
}
public Collection<Object> getSelection() {
return selection;
}
public void setSelection(Collection<Object> selection) {
this.selection = selection;
}
public Collection<Object> getExtensionSelection() {
return extensionSelection;
}
public void setExtensionSelection(Collection<Object> extensionSelection) {
this.extensionSelection = extensionSelection;
}
public List<PackageClass> getPackageList() {
return packageList;
}
public void setPackageList(ArrayList<PackageClass> packageList) {
this.packageList = packageList;
}
public PackageClass getSelectionPackage() {
if (selectionPackage == null || selectionPackage.isEmpty()) {
return null;
}
return selectionPackage.get(0);
}
public void setSelectionPackage(ArrayList<PackageClass> selectionPackage) {
this.selectionPackage = selectionPackage;
}
public ArrayList<PackageClass> getSelectionPackages() {
return selectionPackage;
}
public ExtensionClass getSelectionExtension() {
if (selectionExtension == null || selectionExtension.isEmpty()) {
return null;
}
return selectionExtension.get(0);
}
public void setSelectionExtension(ArrayList<ExtensionClass> selectionExtension) {
this.selectionExtension = selectionExtension;
}
public ArrayList<ExtensionClass> getSelectionExtensions() {
return selectionExtension;
}
}
As the title explains by itself, I have an issue with managing the currently active tab in the tab menu. I'm using JSF 2.1 w/ PF 3.4. Here is the code fragment with the tab menu:
<h:form>
<p:tabMenu activeIndex="#{navigationMB.activeIndex}" >
<p:menuitem value="Početna" action="#{navigationMB.navigateStudent('home')}" icon="ui-icon-home" />
<p:menuitem value="Konsultacije" action="#{navigationMB.navigateStudent('konsultacije')}" icon="ui-icon-search" />
<p:menuitem value="Zakazivanje" action="#{navigationMB.navigateStudent('zakazivanje')}" icon="ui-icon-document"/>
<p:menuitem value="Profesori" action="#{navigationMB.navigateStudent('profesori')}"/>
<p:menuitem value="Moj profil" action="#{navigationMB.navigateStudent('profil')}" icon="ui-icon-person" />
</p:tabMenu>
</h:form>
Here is the code of the backing bean which serves for the sole purpose of navigating that tab menu:
#Named(value = "navigationMB")
#RequestScoped
public class NavigationMB {
private int activeIndex = 0;
public NavigationMB() {
}
public String navigateStudent(String page) {
System.out.println("go to page " + page);
if ("home".equals(page)) {
activeIndex = 0;
return "/student/home?faces-redirect=true";
}
if ("konsultacije".equals(page)) {
activeIndex = 1;
return "/student/allConsults?faces-redirect=true";
}
if ("zakazivanje".equals(page)) {
activeIndex = 2;
return "/student/newConsult?faces-redirect=true";
}
if ("profesori".equals(page)) {
activeIndex = 3;
return "/student/allProfessors?faces-redirect=true";
}
if ("profil".equals(page)) {
activeIndex = 4;
return "/student/profile?faces-redirect=true";
}
return "";
}
This runs fine when just browsing, but when I logout (invalidate the session) and later return with same or different user, the activeIndex is remembered. Am I not understanding something here? I suppose that the request scoped bean would be created every time there's a navigation action, and even if the user doesn't navigate anywhere, the integer I set to 0 would always point to "home" but it doesn't.
Any help would be awesome.
edit:
It seems that even without logging out, when two users (two tabs in browser) navigate around, if user 1 clicks on, for instance, tab menu item 2, and user 2 refreshes his page, user 2 will see tab menu item 2 selected as well, and vice versa.
edit2: I made a mistake with the previous edit, please forget about this above (I didn't notice that refresh on user 2 side actually loads user 1 with his view).
As discussed among the comments of the question, the bean is not recognized as being request scoped. It is created during application startup and lives as long as the application is running.
As Spring is used, using Spring annotations will resolve this issue:
#Scope("request")
public class NavigationMB {
}
For a request scoped bean, or:
#Scope("session")
public class NavigationMB {
}
to make it session scoped.
I'm using primefaces 3.0.M2 with backing bean to add files arranged in folders (modules) and subfolders(assignments). I have managed to do that successfully, but I can't have control over the file to make it downloadable. I want to make the file as a button to download that specific file instead of just being a normal text. Please check the jsf code below:
<p:tree id="tree" value="#{files.root}" var="doc" selectionMode="single"
selection="#{files.selectedTreeNode}">
<p:treeNode>
<h:outputText value="#{doc}"/>
</p:treeNode>
</p:tree>
Here is my backing bean class:
public class FilesBean implements Serializable {
private TreeNode root;
public TreeNode getRoot() {
root = new DefaultTreeNode("root", null);
TreeNode general = new DefaultTreeNode("General", root);
TreeNode module = null;
TreeNode assignment = null;
TreeNode fileNode = null;
if(getMoudles()!=null)
{
for(String s : getMoudles())
{
module = new DefaultTreeNode(s, root);
if(getAssignments()!=null)
{
for (Assignments as : getAssignments())
{
if(as.getMoudleid().equals(s))
assignment = new DefaultTreeNode(as.getAssignmentsPK().getAssignmentid(), module);
for(Files file : getFiles())
{
if (file.getFilesPK().getAssignmentid().equals(as.getAssignmentsPK().getAssignmentid()) && file.getThemodule().equals(s))
{fileNode = new DefaultTreeNode(file,assignment);}
}
}
}
}
}
return root;
}
PS: PrimeFaces 3.0.M2, JSF 2.0, J2EE 6 Web, Servlet 3.0, Glassfish 3.0, EJB 3.0, browser: IE8 also tried on FireFox 3.6.12
Have you tried using a <p:commandButton> with <p:fileDownload>?
<p:commandButton
value="Download"
title="Download"
image="ui-icon-arrowthick-1-s"
ajax="false">
<p:fileDownload value="#{myBean.fileStreamedContent}" />
</p:commandButton>
In your backing bean (for example purposes, assuming your files are JPEGs):
public StreamedContent getFileStreamedContent() {
try {
InputStream is = new BufferedInputStream(
new FileInputStream("/your/file/path/fileXYZ.jpg"));
return new DefaultStreamedContent(is, "image/jpeg", "fileXYZ.jpg");
} catch (FileNotFoundException e) {
}
}
The last part is associating a particular file with a particular tree node. You can use the <p:tree> attributes selectionMode="single" and selection="#{myBean.selectedTreeNode}". The user selects a tree node and this will cause the selectedTreeNode to be set (via a setter method) on your bean.
private TreeNode selectedTreeNode;
public void setSelectedTreeNode(TreeNode selectedTreeNode) {
this.selectedTreeNode = selectedTreeNode;
if (this.selectedTreeNode != null) {
Object yourTreeNodeData = this.selectedTreeNode.getData();
// do whatever you need to do with the data object...
}
}
In the getFileStreamedContent() method, just use the filename stored in your tree node object as the parameter to the FileInputStream() constructor.
EDIT
Rather than try to embed command buttons in the tree, provide one command button somewhere on the page. When a tree node is selected it can set the associated file (to be downloaded) as a property on your bean. Make your tree look like this:
<p:tree
value="#{myBean.rootTreeNode}"
var="node"
selectionMode="single"
selection="#{myBean.selectedTreeNode}">
<p:ajax event="select" listener="#{myBean.onNodeSelect}" />
<p:ajax event="unselect" listener="#{myBean.onNodeUnselect}" />
</p:tree>
public void onNodeSelect(NodeSelectEvent event) {
// put some logging here...
}
public void onNodeUnselect(NodeUnselectEvent event) {
// put some logging here...
}
Put a println or logging statement in your setSelectedTreeNode method to make sure the setter is being invoked when you click the tree node. Use the getData() method on the TreeNode to get back the data value that you originally put in it when you created the tree. The getFileStreamedContent() method will use that value to deliver the correct file that the user selected by clicking on a tree node.
I have a h:commandLink :
<h:commandLink value=""
actionListener="#{controller.authenticateAccount}"
style="text-decoration: none;"
target="#{controller.userNameGiven ? '_parent' : '' }">
<img src="../images/Profile/authenticateCPButton.gif" border="0" style="padding-left: 2px;"/>
</h:commandLink>
Now controller.userNameGiven is a boolean field and is set to true if username given and otherwise set to false. The h:commandLink is present in a iframe and prior to this the target was set to _parent and then if the username is present then it was redirecting to a page in the same parent window but in other case the iframe was rendered in the parent page which is clearly a bug. Now after the target validation the redirected page is opening in that iframe, which is undesirable. What I am doing wrong?
Thanks and regards.
Edit 1:
I have changed the target to:
target="#{controller.target}"
where:
public String getTarget() {
return target;
}
public void setTarget(String target) {
this.target = target;
}
and
if(this.userName != null && this.userName.trim().length()>0) {
target = "_parent";
FacesContext.getCurrentInstance().getExternalContext().redirect("./somepage");
} else {
target = "";
}
But its still not working and the url somepage is opening in the iframe.
Move the logic into a bean method:
public class Controller
{
// ...
public boolean isUserNameGiven () { /* snip */ }
public String getFooTarget()
{
return this.isUserNameGiven() ? "_parent" : "";
}
// ...
}