I have a tree that is used as menu, so every node is clickable and opens another *.xhtml file. The tree is displayed on every *.xhtml file with templates.
Problem: the tree collapses if redirect to a *.xhtml file. Surprisingly, the selected node stays selected (it is colored as selected). The tree shouldn't collapse!
The tree is generated dynamic, but it is only generated once.
Tested with Primefaces 2.2.1 and 3.0.M2
How can I solve this problem? At primefaces showcase this works.
My code:
<h:form id="formTreeStudents">
<p:tree id="treeGroups"
value="#{studentTree.root}"
var="node"
cache="true"
selectionMode="single"
nodeSelectListener="#{studentTree.onNodeSelect}"
selection="#{studentrTree.selectedNode}"
onselectComplete="ajaxDialog.show();"
update="statusbar userbar">
<p:treeNode>
<h:outputText value="#{node.treeString}" styleClass="treeNodeParent"/>
</p:treeNode>
</p:tree>
<p:ajax event="load" onstart="ajaxDialog.hide();"/>
</h:form>
The bakingBean is sessionScoped. It has getter and setter similar to the example at primefaces showcase and a listener function.
#ManagedBean
#SessionScoped
public class StudentTree implements Serializable{
...
public void onNodeSelect(NodeSelectEvent event) {
...
}
}
The tree node stays selected because the property #{studentrTree.selectedNode} of the managed bean has a value.
Your managed bean is #SessionScoped so it will live in session even after you navigate away from and back to the page. If you were to change it to #ViewScoped then the managed bean will die when navigating away from the page, and when you navigate back to the page the property selectedNode will be its default value again.
solved it.
it works with Primefaces 3.0.M2. Something was wrong with my libraries or with cached data.
Some changes had to be done to use 3.0.M2.
f.e.:
nodeSelectListener="#{studentTree.onNodeSelect}"
is now replaced with
<p:ajax event="select" listener="#{studentTree.onNodeSelect}"/>
Related
I have added PrimeFaces schedule from this page and got the results like the following:
I got the following events working fine but how do I get and handle events when prev or next is clicked?
I have also highlighted some more in the image:
<p:ajax event="dateSelect" listener="#{scheduleJava8View.onDateSelect}" update="eventDetails" oncomplete="PF('eventDialog').show();" />
<p:ajax event="eventSelect" listener="#{scheduleJava8View.onEventSelect}" update="eventDetails" oncomplete="PF('eventDialog').show();" />
<p:ajax event="eventMove" listener="#{scheduleJava8View.onEventMove}" update="messages" />
<p:ajax event="eventResize" listener="#{scheduleJava8View.onEventResize}" update="messages" />
To capture dates / view changes on the server / in your bean, I found it easiest to just go for lazy loading (showcase, documentation). This will basically allow you to have a method in the bean where the start and end date are passed in case the view changes:
lazyModel = new LazyScheduleModel() {
#Override
public void loadEvents(LocalDateTime start, LocalDateTime end) {
//
}
};
.. and as a bonus, your events will be lazily loaded!
Note that the type of dates (java.time.LocalDateTime or java.util.Date) will depend on the PrimeFaces version. See the migration guide.
To modify the UI, you need to know that PrimeFaces is using FullCalendar for the p:schedule component. You can use the extender attribute and configure the FullCalendar to your needs. See the toolbar documentation. Note that the version of FullCalendar will depend on the PrimeFaces version. Again, see the migration guide.
To set the time format, use the timeFormat attribute. It uses Moment.js. You could use hh:mmA. Try it on https://www.primefaces.org/showcase/ui/data/schedule/configureable.xhtml
I am working with Primefaces 6.2 Schedule component for a few days now and I can't find an answer to solve my issues using the component. I need some technical advice on this matter.
I've created a view with the Schedule component inside a composition like so:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:form id="content-form">
<p:outputPanel id="page-title-myevents">
<h3>#{translations['pvm_myevents']}</h3>
</p:outputPanel>
<h5>#{translations['misc_myscheduler']}</h5>
<p:schedule id="myScheduler" value="#{myEventsBean.eventModel}" widgetVar="myscheduler" timeZone="#{appSettingsBean.uiTimeZone}">
<p:ajax event="dateSelect" listener="#{myEventsBean.onDateSelect}" update="myEventDetails" oncomplete="PF('myEventDialog').show();" />
<p:ajax event="eventSelect" listener="#{myEventsBean.onEventSelect}" update="myEventDetails" oncomplete="PF('myEventDialog').show();" />
<p:ajax event="eventMove" listener="#{myEventsBean.onEventMove}" update="myEventMessages" />
<p:ajax event="eventResize" listener="#{myEventsBean.onEventResize}" update="myEventMessages" />
</p:schedule>
<p:dialog widgetVar="myEventDialog" header="Event details" modal="true">
<h:panelGrid id="myEventDetails" columns="2">
<p:outputLabel for="myEventTitle" value="#{translations['fld_eventtitle']}" />
<p:inputText id="myEventTitle" value="#{myEventsBean.event.title}" required="true" />
<p:outputLabel for="myEventFrom" value="#{translations['fld_from']}" />
<p:calendar id="myEventFrom" value="#{myEventsBean.dateFrom}" timeZone="#{appSettingsBean.uiTimeZone}" pattern="#{appSettingsBean.uiDateTimePattern}" />
<p:outputLabel for="myEventTo" value="#{translations['fld_to']}" />
<p:calendar id="myEventTo" value="#{myEventsBean.dateTo}" timeZone="#{appSettingsBean.uiTimeZone}" pattern="#{appSettingsBean.uiDateTimePattern}" />
<p:outputLabel for="myEventAllDay" value="#{translations['fld_allday']}" />
<h:selectBooleanCheckbox id="myEventAllDay" value="#{myEventsBean.event.allDay}" />
<p:commandButton id="myEventResetForm" type="reset" value="#{translations['btn_reset']}" />
<p:commandButton id="myEventUpdate" value="Save" action="#{myEventsBean.addEvent}" oncomplete="PF('myscheduler').update();PF('myEventDialog').hide();" />
</h:panelGrid>
</p:dialog>
<p:messages id="myEventMessages" showDetail="true" closable="true">
<p:autoUpdate />
</p:messages>
<hr></hr>
</h:form>
</ui:composition>
I have various compositions and they all get loaded inside my dashboard.xhtml like so:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<ui:include src="/themes/theme.xhtml"/>
<h:body>
<ui:insert name="header" >
<ui:include src="/main-dashboard/my-topnav.xhtml"/>
</ui:insert>
<ui:insert name="content" >
<ui:include src="/main-dashboard/my-sidenav.xhtml"/>
<p:outputPanel id="dashboard-container">
<ui:include src="/main-dashboard/my-sidenavtoggler.xhtml"/>
<p:outputPanel id="content-window">
<p:outputPanel id="content-panel">
<ui:include src="#{contentLoaderBean.mainContent}" />
</p:outputPanel>
</p:outputPanel>
</p:outputPanel>
</ui:insert>
</h:body>
</html>
This is my first composition that's actually built (others are still empty). I load a simple ScheduleModel to it on #PostConstruct inside a #ViewScoped bean.
Since I'don't have any events in my database yet, I set the model like so: setEventModel(new DefaultScheduleModel());
FIRST ISSUE: If I put some random generated events inside a model, sometimes they get displayed in the view, sometimes they don't. I don't understand why this happens at all. I don't get any errors in Java or Javascript console, it's just random. Lazy model works the same.
SECOND ISSUE: Empty or full Schedule model, doesn't matter. When the page loads I usually get a Javascript warning saying:
jquery.js.xhtml?ln=primefaces&v=6.2:4 [Deprecation] Synchronous
XMLHttpRequest on the main thread is deprecated because of its
detrimental effects to the end user's experience. For more help, check
https://xhr.spec.whatwg.org/
THIRD ISSUE: You may have noticed I also have a dialog inside the content form. This dialog fires on date select event and when I try and select a date from the datepicker component it throws an interesting Javascript error (uncaught type error) like so:
It's interesting because if I try to do the same thing on Firefox it throws a different error like so:
Microsoft Edge doesn't throw errors at all.
NOTICE:
Datepicker could be an issue as well since it doesn't pop up when schedule loads and shows a model with randomly generated data. If scheduler fails to load the model, datepicker will pop-up and throw the uncaught type error when any date is selected.
It doesn't matter which date I select, errors are thrown. Since Ajax requests don't fire correctly, bean methods don't fire at all, so I think it has to be something on the view side that needs to be fixed properly.
I've tried and disabled all custom css and js imports (am using Bootstrap 4.2.1 css and js for design purposes) and manually cleaned deployment directories. I also made sure my project is loaded without old resources by clearing browser history and cache. I had no luck fixing these issues so far (all warnings and errors remain the same).
I don't know if all three issues are related or not but I've put them in the same post. Sometimes solving one issue, solves others as well. Since they all happen in the same composition this just might be the case again.
Let me know if I can provide more detail in any way and I'll do what I can.
Thank you.
EDIT: Based on a received comment from #Melloware. Upgrading Primefaces 6.2 to Primefaces 7-RC2 solved some issues for me. Deprecation warnings and uncaught type errors are gone now. First issue still remains. Schedule component doesn't show schedule objects or "events". During debug mode, I've found out that schedule objects are created and are pushed to the schedule model. All I need now, is the view component to show them.
Since I was able to solve the last piece of my puzzle, Schedule not displaying my schedule objects, I'll write a full answer to my question.
Answer provided by #Melloware helped me move forward with my core design. Upgrading Primefaces 6.2 to Primefaces 7-RC2 removed deprecation warnings and uncaught type errors. Now I was able to locate and implement a solution for my final issue, loading schedule objects.
I've made a rookie mistake loading my contents through my content loader bean. To be precise, I've implemented content navigation while pushing links to my content loader bean which handles what should be loaded next when navigation action is executed. Navigation actions should be called with Action properties from CommandLink components. Here is where I made my design mistake. I used the ActionListener property instead, which resulted in a situation where my content didn't get loaded properly.
Here is a quote from #BalusC post that got my wheels spinning again:
The action method can (thus, not must) return a String which will be
used as navigation case outcome (the target view). A return value of
null or void will let it return to the same page and keep the current
view scope alive. A return value of an empty string or the same view
ID will also return to the same page, but recreate the view scope and
thus destroy any currently active view scoped beans and, if
applicable, recreate them.
Full post can be found here: differences-between-action-and-actionlistener
I've learned something new today.
Thank you!
"anymore" is definitely a key word here. I had this working, and even after comparing my previous revisions, I cannot see a smoking gun.
I have placed an accordion in the navigation panel on the West side of my layout. I have overridden the actionListener to call a remoteCommand, like this.
<p:accordionPanel widgetVar="tabPanel"
dynamic="true" cache="true"
activeIndex="-1"
actionListener="tabChange()">
<p:remoteCommand name="tabChange"
process="#this"
update=":contentPanel"
actionListener="#{viewSelectionBean.changeView}" />
When clicking on any given tab, it used to call the backing bean method changeView, which sets the html page being shown in ":contentPanel", but now I get no backing bean action. I have commandLinks within each of these accordion tabs that also call changeView successfully. Its only the tabChange() that doesn't seem to be called.
actionListener is not a property of accordionPanel, therefore, thats why it wouldn't be called. This feature can be made to work using ajax, but it demonstrates lag while expanding each tab. Lag aside, one might also have success overriding onTabChange of the accordionPanel, but that will force you to have to manually effect the activeIndex, and the expanding of tabs.
<p:accordionPanel widgetVar="tabPanel"
dynamic="true" cache="true"
activeIndex="-1">
<p:ajax event="tabChange"
listener="#{viewSelectionBean.onTabChange}"
update=":contentPanel"
process="#this"
partialSubmit="true"/>
I see that primeface p:graphicImage in my form is causing a new windowId to be created with in the same browser tab.
All my beans are window scoped. #WindowScoped of Myface CODI.
Since my business logic is tied to the initial login, the environment variables are tied to the windowContext.
When p:graphicImage tries to access the bean with a new windowId/windowContext, the application is failing.
Is there a way to avoid this?
Here is my view file
<h:form enctype="multipart/form-data">
<p:messages />
<p:panelGrid style="width:75%;margin:5px auto;">
<f:facet name="header">
<p:row>
<p:column colspan="3">
<h:outputText value="#{title.update}" />
</p:column>
</p:row>
</f:facet>
<p:row>
<p:column>
<p:graphicImage alt="Your Photograph" id="photo" value="#{employeeUpdateBean.photoStream}" width="80" height="80" />
</p:column>
<p:column colspan="2">
<p:fileUpload mode="advanced"
fileUploadListener="#{employeeUpdateBean.addPhotoFile}"
allowTypes="/(\.|\/)(gif|jpe?g)$/" sizeLimit="100000"
invalidSizeMessage="Please limit photo size to 100Kb"
/>
</p:column>
</p:row>
<f:facet name="footer">
<p:row>
<p:column colspan="3">
<p:commandButton value="Update" action="#{employeeUpdateBean.employeeUpdate}" ajax="false"
style="margin-left:5px;margin-right:5px;" />
</p:column>
</p:row>
</f:facet>
</p:panelGrid>
</h:form>
Here is part of my bean
#Named
#WindowScoped
public class EmployeeUpdateBean implements Serializable{
static final long serialVersionUID = 7l;
private static final Log log = LogFactory.getLog(EmployeeUpdateBean.class);
#Inject
private HibernateUtil hibernateUtil;
#Inject
securityHelper secHelper;
#Inject
WindowContext windowContext;
public EmployeeUpdateBean() {
}
#PostConstruct
public void getData() {
System.out.println("In Get Data");
System.out.println("windowId: "+this.windowContext.getId());
//Thread.dumpStack();
Integer id= secHelper.getEmployeeId();
System.out.println("ID"+id);
}
Below is the output I see.
In Get Data
windowId: f75
ID11117
In Get Data
windowId: f75
ID11117
In Get Data
windowId: 1f9
IDnull
This first two 'in Get Data' are related to a preRenderView call to getData (not shown in code here) and the PostContruct call.
The third is clearly from the call to #PostConstruct when a new bean instance is created when p:graphicImage tries to access the photoStream with a new windowId.
I have tried this by removing the p:graphicImage from the form, and in that case the third call is never made.
I have to use p:graphicImage becasue I need to stream data from the DB. And I am trying to avoid writing a seperate servlet to stream images.
Also, the seperate servlet is not a good option as I need to know the employee who is logged in to be able to show the image.
Please let me know if there are any good solutions to get over this.
My full environment is
Tomcat 7
Openwebbeans
Myfaces CODI
Myfaces + Primefaces
there are many questions here in stackoverflow regarding the use of p:graphicImage to render images from database..
In order to make it work, the bean has to be #RequestScoped or #SessionScoped. I don't think it will work with special scoped from CODI.
I suggest you use a servlet for this matter. if you need to know the employee who is logged in, you can put that information in the session map, and then read it from server.
The following explanation is from primefaces user's guide:
Dynamic image display works as follows:
• Dynamic image puts its value
expression string to the http session with a unique key.
• Unique
session key is appended to the image url that points to JSF resource
handler.
• Custom PrimeFaces ResourceHandler get the key from the url,
retrieves the expression string like
#{bean.streamedContentValue}, evaluates it to get the instance of StreamedContent from bean and streams contents to client.
As a result
there will be 2 requests to display an image, first browser will make
a request to load the page and then another one to the dynamic image
url that points to JSF resource handler. Please note that you cannot
use viewscope beans as viewscoped bean is not available in resource
loading request.
How can I use an AJAX listener inside a tabview. Whenever the tab opened(or for a mouse click anywhere), the listener need to execute. I tried with event=click,change,blur etc, but not worked.
<p:tabView activeIndex="#{backingbean.tanIndex}">
<p:ajax event="?" listener="#{backingbean.setTabIndex}" />
in view.jsf:
<p:tabView>
<p:ajax event="tabChange" listener="#{employeeEdit.onTabChange}">
in edit.jsf:
<p:tabView activeIndex="#{employeeEdit.tabIndex}">
in backingBean:
private int tabIndex;
public int onTabChange(TabChangeEvent event)
{
// Here I'm getting event.getTab().getId() and set it to `tabIndex` property.
}
When editing I need redirect to the that tab which is active in view. So if I didn't change the tab onTabChange() will not execute and tabIndex has its old value only.
I'm using Primefaces version-3.0.M3.
It looks like this was a Primefaces bug that was fixed in the newest 3.0.1 release:
http://forum.primefaces.org/viewtopic.php?f=3&t=17288
I had a similar problem with Primefaces 5.1
As long as i put the tabview into a form everything worked fine.
But because i wanted to use seperate forms in my tabs i had to remove the surrounding form of the tabview to avoid nested forms.
Without the surrounding form the ajax event didn´t get triggered any more when changing the tab.
My solution was to use a remotecommand in a form parallel to the tabview.
The remotecommand is triggered by the onTabChange attribute of the tabview element.
At that call i forwarded the index parameter to the global request parameters.
<p:tabView id="rootTabMenu" styleClass="tabcontainer" prependId="false"
activeIndex="#{sessionData.activeTabIndex}" widgetVar="rootTabMenu"
onTabChange="tabChangeHelper([{name: 'activeIndex', value: index}])">
// Tabs...
</p:tabView>
<h:form id="tabChangeHelperForm">
<p:remoteCommand name="tabChangeHelper" actionListener="#{sessionData.onTabChange()}" />
</h:form>
In the backing bean i catched the value again from the request parameter map and set the active index.
public void onTabChange()
{
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> paramMap = context.getExternalContext().getRequestParameterMap();
String paramIndex = paramMap.get("activeIndex");
setActiveTabIndex(Integer.valueOf(paramIndex));
System.out.println("Active index changed to " + activeTabIndex);
}
Hope that can help you
Not sure if what I am writing is true for ver 3.0.M3. I have in front of the documentation of ver 3.0RC2 and there is a paragraph about this, with explaination and sample code (chapter TabView, paragraph Ajax Behaviour Events). You should have a look at that.
This is the part of the sample code that should help most:
<p:tabView>
<p:ajax event=”tabChange” listener=”#{bean.onChange}” />
</p:tabView>
Jaron has an answer that the 3.0.1 release fixed this but I had this all the way up to 3.5 i believe i was still having this problem. on firefox and IE, the javascript handler for the Tabs weren't firing the ajax event. On google chrome, for whatever reason, it actually worked.
I moved up to Primefaces 5.0 today and this does NOT have the problem any longer. So at the very worst-case, go to Primefaces 5.0 and you'll be all good in the hood