I have my sites content saved as plain html in my database. It is only simple data no input from the user is possible.
I like to show the content as follows:
if content.jsf?Sitename gets called i want to show the content of the site "Sitename".
I already have the content saved in my ApplicationScoped Bean.
content.xhtml:
<ui:composition template="template/common/commonLayout.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:define name="content">
//show content here
</ui:define>
</ui:composition>
I want to do this because, i'd like to add new pages/subpages without redeploying the whole application.
How can I make this work?
You can use <h:outputText escape="false"> to show plain HTML from a bean property.
<h:outputText value="#{yourApplicationScopedBean.html}" escape="false" />
If you want to parameterize it, use EL 2.2 feature of passing method arguments, or use a Map.
Beware of potential XSS attack holes if this concerns user-controlled data though.
Related
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!
Using Primefaces 6.0/jsf 2.2.6.
I have a page (secure), which includes another page (unsecure, there are 2 points of entry to the unsecure page hence this setup) backed by a bean, which uses a template, which is determined at runtime i.e.:
so first secure page has:
<h:body>
<ui:include src="../unsecure/eacCalculator.xhtml" />
</h:body>
Second page:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:pe="http://primefaces.org/ui/extensions"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<script type="text/javascript">
$(document).on("keypress", ":input:not(text,textarea)", function (event) {
if (event.keyCode == 13) {
event.preventDefault();
}
});
</script>
</h:head>
<ui:composition template="#{eacCalculatorBean.template}" >
<f:event listener="#{eacCalculatorBean.getScreenStartupData()}" type="preRenderComponent" />
<ui:define name="page-content">
.......
If I click on page's URL directly after login from a dynamically built menu item, then page loads fine. If I however go to another page first and then from there click again on the menu item of above page it loads a blank page. If I re-click on menu item, page re-renders fine again.
What possible reasons could it be for not loading first time after another page loaded?
You use an relative path to the include file. If your second page is located inside a different path as the after-login-page, maybe the file location can't be resolved.
take a look as the AS logfile if file location can't be resolved
Try absolute path inside template to exclude this problem
<ui:include src="/path/to/unsecure/eacCalculator.xhtml" />
Ok after much debugging I actually found the issue. The fact that "which template to use" is delayed till bean is created caused the CustomMenu inside the xhtml to only fire after the Bean was instantiated. To make a long story short, it was then using the previous screens settings which was causing the css to slide the data to the right (which made it blank on the screen).
I know it seems like a duplicate question (and I found a lot of questions like mine, but none could solve my problem). In fact, as long as it can be a lack of attention of mine, yes it can be a duplicate. Here it is: I have two updates not working well: the most important is one, concerning a button inside a composite component (a p:dialog with its own h:form inside) trying to update a p:autoComplete in another h:form. The composite also receive a listener as a parameter and, in the listener, it updates a property of the bean: this is one of the problems - this property is bound to the value attribute of the p:autoComplete and I was not able to update it after the listener change its value.
The other problem is a p:inputReset which is apparently doing nothing (it should clear up the input fields in the same composite above).
I've already checked out the updates attributes values with the browser development tool, and they're correct.
One more information: the problem started after I put the dialog inside a composite. It used to work fine before it.
[EDITED]: These are some of the topics I've researched:
How to update a composite component form from another composite component?: The composite component already had an update attribute in the cc:interface section and it's not helping with this problem. #stg said it's a bad design to put a form inside a composite component, but would it prevent it from updating other components? [EDITED 2]: Anyway, I moved the form out of the composite (and moved the component into a form). The problem remains.
How to find out client ID of component for ajax update/render? Cannot find component with expression “foo” referenced from “bar”: Very detailed #BalusC answer. I already checked the paths to the component being updated and they seem to be correct (actually, cc.parent.namingContainer.clientId and other syntactic sugar is not getting the clientId, maybe some of them are deprecated - the answer was wrote in 2011). Anyway, all the working approaches pointed there result in the same path I put in the example bellow.
Updating a component outside of the component's context: I've tried with and without the leading ":". Made no difference.
There are other questions about this topic all over the Internet, but they are variations of this problem and most of them could be solved with the same things pointed by #BalusC in the link above.
In my case the behavior occured in a structure like this (simplified):
A template:
...
<h:body>
<h:form id="dlgTemplateForm">
<p:tabView id="tbvMain">
<ui:insert name="tabs" />
</p:tabView>
</h:form>
<ui:insert name="outsideDlgTemplateForm" />
</h:body>
I also have a composite component (dlgComp.xhtml) that looks like:
<cc:interface>
<cc:attribute name="returnListener" method-signature="void listener()" />
<cc:attribute name="bean" type="com.foo.BeanClass" />
<cc:attribute name="widgetVar" />
<cc:attribute name="update" />
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<p:dialog id="dlg" widgetVar="#{cc.attrs.widgetVar}">
<h:form id="dlgForm">
<p:inputText id="ipm" value="#{cc.attrs.bean.obj}" />
<!--here is the componentn with the update which doesn't work-->
<p:commandButton id="btnSave"
actionListener="#{cc.attrs.returnListener}"
value="Gravar"
update="#{cc.attrs.update}"
oncomplete="PF('#{cc.attrs.widgetVar}').hide()"/>
</h:form>
</p:dialog>
</div>
</cc:implementation>
Then, I build myPage.xhtml, based on the template above. Inside it:
<ui:define name="tabs">
<p:tab id="tabInfo">
<ui:include src="myTab.xhtml" />
</p:tab>
</ui:define>
<ui:define name="outsideDlgTemplateForm">
<myComp:dlgComp id="dlgId"
widgetVar="dlgIdWGV" bean="#{myPageBean.myPageManagedProperty}"
returnListener="#{myPageBean.returnFromDialog}"
update=":dlgTemplateForm:tbvMain:acpTest" />
</ui:define>
In myTab.xhmtl (to be included in myPage.xhtml), I have this:
<p:autoComplete id="acpTest" value="#{myPageBean.prop}"
completeMethod="#{myPageBean.acpCompleteText}" />
<p:commandButton actionListener="#{myPage.listener}"
oncomplete="PF('dlgIdWGV').show();"
update=":dlgId:dlgForm" process="#this">
<p:resetInput target=":dlgId:dlgForm" /> <!--this doesn't work too-->
</p:commandButton>
In myPageBean.java
#ManagedProperty(value = "beanClass")
private com.foo.BeanClass myPageManagedProperty;
private Object prop;
//getters and setters
public void returnFromDialog(void) {
this.prop = myPageManagedProperty.getObj();
}
And, finally, in com.foo.BeanClass
private Object obj;
//getter and setter
The following code is inspired from PrimeFaces DataGrid + DataTable Tutorials and put into a <p:tab> of a <p:tabView> residing in a <p:layoutUnit> of a <p:layout>. Here is the inner part of the code (starting from p:tab component); the outer part is trivial.
<p:tabView id="tabs">
<p:tab id="search" title="Search">
<h:form id="insTable">
<p:dataTable id="table" var="lndInstrument" value="#{instrumentBean.instruments}">
<p:column>
<p:commandLink id="select" update="insTable:display" oncomplete="dlg.show()">
<f:setPropertyActionListener value="#{lndInstrument}"
target="#{instrumentBean.selectedInstrument}" />
<h:outputText value="#{lndInstrument.name}" />
</p:commandLink>
</p:column>
</p:dataTable>
<p:dialog id="dlg" modal="true" widgetVar="dlg">
<h:panelGrid id="display">
<h:outputText value="Name:" />
<h:outputText value="#{instrumentBean.selectedInstrument.name}" />
</h:panelGrid>
</p:dialog>
</h:form>
</p:tab>
</p:tabView>
When I click the <p:commandLink>, the code stops working and gives the message:
Cannot find component with expression "insTable:display" referenced from "tabs:insTable:select".
When I try the same using <f:ajax>, then it fails with a different message basically telling the same:
<f:ajax> contains an unknown id "insTable:display" cannot locate it in the context of the component "tabs:insTable:select"
When it happens during another Ajax postback and the JSF project stage is set to Development, then it fails with a JavaScript alert with the message:
malformedXML: During update: insTable:display not found
How is this caused and how can I solve it?
Look in HTML output for actual client ID
You need to look in the generated HTML output to find out the right client ID. Open the page in browser, do a rightclick and View Source. Locate the HTML representation of the JSF component of interest and take its id as client ID. You can use it in an absolute or relative way depending on the current naming container. See following chapter.
Note: if it happens to contain iteration index like :0:, :1:, etc (because it's inside an iterating component), then you need to realize that updating a specific iteration round is not always supported. See bottom of answer for more detail on that.
Memorize NamingContainer components and always give them a fixed ID
If a component which you'd like to reference by ajax process/execute/update/render is inside the same NamingContainer parent, then just reference its own ID.
<h:form id="form">
<p:commandLink update="result"> <!-- OK! -->
<h:panelGroup id="result" />
</h:form>
If it's not inside the same NamingContainer, then you need to reference it using an absolute client ID. An absolute client ID starts with the NamingContainer separator character, which is by default :.
<h:form id="form">
<p:commandLink update="result"> <!-- FAIL! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
<p:commandLink update=":result"> <!-- OK! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
<p:commandLink update=":result"> <!-- FAIL! -->
</h:form>
<h:form id="otherform">
<h:panelGroup id="result" />
</h:form>
<h:form id="form">
<p:commandLink update=":otherform:result"> <!-- OK! -->
</h:form>
<h:form id="otherform">
<h:panelGroup id="result" />
</h:form>
NamingContainer components are for example <h:form>, <h:dataTable>, <p:tabView>, <cc:implementation> (thus, all composite components), etc. You recognize them easily by looking at the generated HTML output, their ID will be prepended to the generated client ID of all child components. Note that when they don't have a fixed ID, then JSF will use an autogenerated ID in j_idXXX format. You should absolutely avoid that by giving them a fixed ID. The OmniFaces NoAutoGeneratedIdViewHandler may be helpful in this during development.
If you know to find the javadoc of the UIComponent in question, then you can also just check in there whether it implements the NamingContainer interface or not. For example, the HtmlForm (the UIComponent behind <h:form> tag) shows it implements NamingContainer, but the HtmlPanelGroup (the UIComponent behind <h:panelGroup> tag) does not show it, so it does not implement NamingContainer. Here is the javadoc of all standard components and here is the javadoc of PrimeFaces.
Solving your problem
So in your case of:
<p:tabView id="tabs"><!-- This is a NamingContainer -->
<p:tab id="search"><!-- This is NOT a NamingContainer -->
<h:form id="insTable"><!-- This is a NamingContainer -->
<p:dialog id="dlg"><!-- This is NOT a NamingContainer -->
<h:panelGrid id="display">
The generated HTML output of <h:panelGrid id="display"> looks like this:
<table id="tabs:insTable:display">
You need to take exactly that id as client ID and then prefix with : for usage in update:
<p:commandLink update=":tabs:insTable:display">
Referencing outside include/tagfile/composite
If this command link is inside an include/tagfile, and the target is outside it, and thus you don't necessarily know the ID of the naming container parent of the current naming container, then you can dynamically reference it via UIComponent#getNamingContainer() like so:
<p:commandLink update=":#{component.namingContainer.parent.namingContainer.clientId}:display">
Or, if this command link is inside a composite component and the target is outside it:
<p:commandLink update=":#{cc.parent.namingContainer.clientId}:display">
Or, if both the command link and target are inside same composite component:
<p:commandLink update=":#{cc.clientId}:display">
See also Get id of parent naming container in template for in render / update attribute
How does it work under the covers
This all is specified as "search expression" in the UIComponent#findComponent() javadoc:
A search expression consists of either an identifier (which is matched exactly against the id property of a UIComponent, or a series of such identifiers linked by the UINamingContainer#getSeparatorChar character value. The search algorithm should operates as follows, though alternate alogrithms may be used as long as the end result is the same:
Identify the UIComponent that will be the base for searching, by stopping as soon as one of the following conditions is met:
If the search expression begins with the the separator character (called an "absolute" search expression), the base will be the root UIComponent of the component tree. The leading separator character will be stripped off, and the remainder of the search expression will be treated as a "relative" search expression as described below.
Otherwise, if this UIComponent is a NamingContainer it will serve as the basis.
Otherwise, search up the parents of this component. If a NamingContainer is encountered, it will be the base.
Otherwise (if no NamingContainer is encountered) the root UIComponent will be the base.
The search expression (possibly modified in the previous step) is now a "relative" search expression that will be used to locate the component (if any) that has an id that matches, within the scope of the base component. The match is performed as follows:
If the search expression is a simple identifier, this value is compared to the id property, and then recursively through the facets and children of the base UIComponent (except that if a descendant NamingContainer is found, its own facets and children are not searched).
If the search expression includes more than one identifier separated by the separator character, the first identifier is used to locate a NamingContainer by the rules in the previous bullet point. Then, the findComponent() method of this NamingContainer will be called, passing the remainder of the search expression.
Note that PrimeFaces also adheres the JSF spec, but RichFaces uses "some additional exceptions".
"reRender" uses UIComponent.findComponent() algorithm (with some additional exceptions) to find the component in the component tree.
Those additional exceptions are nowhere in detail described, but it's known that relative component IDs (i.e. those not starting with :) are not only searched in the context of the closest parent NamingContainer, but also in all other NamingContainer components in the same view (which is a relatively expensive job by the way).
Never use prependId="false"
If this all still doesn't work, then verify if you aren't using <h:form prependId="false">. This will fail during processing the ajax submit and render. See also this related question: UIForm with prependId="false" breaks <f:ajax render>.
Referencing specific iteration round of iterating components
It was for long time not possible to reference a specific iterated item in iterating components like <ui:repeat> and <h:dataTable> like so:
<h:form id="form">
<ui:repeat id="list" value="#{['one','two','three']}" var="item">
<h:outputText id="item" value="#{item}" /><br/>
</ui:repeat>
<h:commandButton value="Update second item">
<f:ajax render=":form:list:1:item" />
</h:commandButton>
</h:form>
However, since Mojarra 2.2.5 the <f:ajax> started to support it (it simply stopped validating it; thus you would never face the in the question mentioned exception anymore; another enhancement fix is planned for that later).
This only doesn't work yet in current MyFaces 2.2.7 and PrimeFaces 5.2 versions. The support might come in the future versions. In the meanwhile, your best bet is to update the iterating component itself, or a parent in case it doesn't render HTML, like <ui:repeat>.
When using PrimeFaces, consider Search Expressions or Selectors
PrimeFaces Search Expressions allows you to reference components via JSF component tree search expressions. JSF has several builtin:
#this: current component
#form: parent UIForm
#all: entire document
#none: nothing
PrimeFaces has enhanced this with new keywords and composite expression support:
#parent: parent component
#namingcontainer: parent UINamingContainer
#widgetVar(name): component as identified by given widgetVar
You can also mix those keywords in composite expressions such as #form:#parent, #this:#parent:#parent, etc.
PrimeFaces Selectors (PFS) as in #(.someclass) allows you to reference components via jQuery CSS selector syntax. E.g. referencing components having all a common style class in the HTML output. This is particularly helpful in case you need to reference "a lot of" components. This only prerequires that the target components have all a client ID in the HTML output (fixed or autogenerated, doesn't matter). See also How do PrimeFaces Selectors as in update="#(.myClass)" work?
first of all: as far as i know placing dialog inside a tabview is a bad practice... you better take it out...
and now to your question:
sorry, took me some time to get what exactly you wanted to implement,
did at my web app myself just now, and it works
as I sayed before place the p:dialog out side the `p:tabView ,
leave the p:dialog as you initially suggested :
<p:dialog modal="true" widgetVar="dlg">
<h:panelGrid id="display">
<h:outputText value="Name:" />
<h:outputText value="#{instrumentBean.selectedInstrument.name}" />
</h:panelGrid>
</p:dialog>
and the p:commandlink should look like this (all i did is to change the update attribute)
<p:commandLink update="display" oncomplete="dlg.show()">
<f:setPropertyActionListener value="#{lndInstrument}"
target="#{instrumentBean.selectedInstrument}" />
<h:outputText value="#{lndInstrument.name}" />
</p:commandLink>
the same works in my web app, and if it does not work for you , then i guess there is something wrong in your java bean code...
It's because the tab is a naming container aswell... your update should be update="Search:insTable:display" What you can do aswell is just place your dialog outside the form and still inside the tab then it would be: update="Search:display"
Please note that from PrimeFaces 10 and up, you are able to use observer and event.
This allows you to update components based on a custom event name, set by the #obs(event) keyword. For example:
<p:commandButton update="#obs(myEvent)"/>
<h:panelGroup>
<p:autoUpdate on="myEvent"/>
</h:panelGroup>
See:
https://www.primefaces.org/showcase/ui/ajax/observer.xhtml
I know this already has a great answer by BalusC but here is a little trick I use to get the container to tell me the correct clientId.
Remove the update on your component that is not working
Put a temporary component with a bogus update within the component you were trying to update
hit the page, the servlet exception error will tell you the correct client Id you need to reference.
Remove bogus component and put correct clientId in the original update
Here is code example as my words may not describe it best.
<p:tabView id="tabs">
<p:tab id="search" title="Search">
<h:form id="insTable">
<p:dataTable id="table" var="lndInstrument" value="#{instrumentBean.instruments}">
<p:column>
<p:commandLink id="select"
Remove the failing update within this component
oncomplete="dlg.show()">
<f:setPropertyActionListener value="#{lndInstrument}"
target="#{instrumentBean.selectedInstrument}" />
<h:outputText value="#{lndInstrument.name}" />
</p:commandLink>
</p:column>
</p:dataTable>
<p:dialog id="dlg" modal="true" widgetVar="dlg">
<h:panelGrid id="display">
Add a component within the component of the id you are trying to update using an update that will fail
<p:commandButton id="BogusButton" update="BogusUpdate"></p:commandButton>
<h:outputText value="Name:" />
<h:outputText value="#{instrumentBean.selectedInstrument.name}" />
</h:panelGrid>
</p:dialog>
</h:form>
</p:tab>
</p:tabView>
Hit this page and view the error.
The error is:
javax.servlet.ServletException: Cannot find component for expression "BogusUpdate" referenced from
tabs:insTable: BogusButton
So the correct clientId to use would then be the bold plus the id of the target container (display in this case)
tabs:insTable:display
Try change update="insTable:display" to update="display". I believe you cannot prefix the id with the form ID like that.
I have an iFrame in my page looking like this:
<h:panelGroup id="gameDiv">
<f:verbatim>
<iframe src="/levelup/resources/#{cc.attrs.src_dir}/#{cc.attrs.src_html}" width="700px" height="800px" frameborder="0" id="gameFrame">
</iframe>
</f:verbatim>
</h:panelGroup>
Basically, the "src" variable is bound using JSF 2.0 EL, and gets its value from a backing bean.
I then use a form to update this value, and refresh the whole page. In the rendered HTML, I can see that the "src" for my div has been updated. However, the HTML page still shows the old one.
I thought the issue was similar to 2 iframes with the same display even if the src are different, and I tried the solutions that have been mentioned (using a timestamp to make the src unique, or resetting them to "about:blank" on each page load). None of them worked however.
For information, the form that updates the backing bean is:
<h:form id="gameSelectionForm">
<h:selectOneMenu id="gameSelection">
<f:selectItems value="#{gameBean.gameIds}" />
</h:selectOneMenu>
<p:commandButton id="gameSelector" action="#{gameBean.changeGame}" update="gameScoreFieldset, gameDiv" />
</h:form>
Any hint would be much useful.
Thanks in advance,
Sébastien
You're changing the src of the iframe using JS/Ajax, but not reloading its content.
There are 2 ways to fix this:
Just don't use JS/ajax. A synchronous HTTP request will reload the entire document and thus automagically reload the iframe.
<p:commandButton ajax="false" />
Use JS to force reload. Add the following after the <iframe>.
<script>document.getElementById('gameFrame').location.reload()</script>
Oh, you definitely need to remove the <f:verbatim>. Since JSF 1.2 that tag is utterly useless.