Is it possible to update non-JSF components (plain HTML) with JSF ajax?
Is it possible to update parts of my page that are not JSF components?
No. The to-be-updated component has to be available by UIViewRoot#findComponent()
, so that JSF can find them, invoke encodeAll()
on it, capture the generated HTML output and pass back it in the ajax response so that JavaScript can update the HTML DOM tree with it. Plain HTML elements are not represented as real UIComponent
instances in the JSF component tree, so JSF already cannot locate them in first place.
For example, can I update a plain HTML
<div>
or do I need to wrap that in a JSF component?
You need to wrap it in a JSF component like <h:panelGroup>
. You can however just use <h:panelGroup layout="block">
to represent a real <div>
in JSF. This way you don't need to wrap the <div>
in another JSF component.
<h:panelGroup layout="block" id="foo">
...
</h:panelGroup>
Since JSF 2.2 you can use new passthrough elements feature with jsf:id
attribute to declare HTML(5) elements as JSF components.
<... xmlns:jsf="http://xmlns.jcp.org/jsf">
<div jsf:id="foo">
...
</div>
<main jsf:id="bar">
...
</main>
<section jsf:id="baz">
...
</section>
They will render their output as-is, but under the covers be a concrete UIPanel
instance.
There's however one corner case in case of composite components. You can use the following approach to have a HTML element which is updateable by ajax.
<cc:implementation>
<span id="#{cc.clientId}">
...
</span>
</cc:implementation>
The explanation that this approach works is because even though the composite component does not render itself to the HTML output, it is by itself available by UIViewRoot#findComponent()
.
See also:
- How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
- Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?
- Rerendering composite component by ajax
Ajax update of non-JSF component with PrimeFaces selectors
No, that's not possible. The update target must not only in client side be obtainable in HTML DOM tree by document.getElementById()
, but also in server side by UIViewRoot#findComponent()
, so that JSF can regenerate the desired HTML output which ultimately get applied during the ajax update.
If you supply JSF the ID of a plain HTML element, then it won't find anything in the component tree to regenerate the desired new HTML output for. Just replace the plain HTML element by a JSF component.
The PrimeFaces selectors get ultimately converted to HTML element IDs. PrimeFaces will loop over the elements found by the jQuery selector and extract their id
attributes before passing to JSF. This is thus essentially the same problem as already answered here: Is it possible to update non-JSF components (plain HTML) with JSF ajax?.
Update component outside of h:form - ComponentNotFoundException
JSF can't see the id of your div if it is not a JSF component so you need to convert your div to a h:panelGroup
<h:panelGroup id="entryDiv" layout="block">
<div>
<h:form id="myForm">
<c:forEach items="#{foodPlanManagementBean.loadRestaurantsHistory()}" var="restaurantHistoryEntry">
<p:commandButton value="MyName" update=":entryDiv"/>
</div>
</c:forEach>
</h:form>
</div>
</h:panelGroup>
if you don't put layout="block"
it will render a span instead of a div.
Ajax-update another component inside same composite component
<h:inputText ...>
<f:ajax ...render="#{cc.clientId}:table#{cc.clientId}" />
</h:inputText>
<h:dataTable id="table#{cc.clientId}" ...>
This is unnecessarily clumsy. Both components are in the same naming container (the composite itself!), so the prefix is implicitly already done by the composite itself. The suffix is valid, but just unnecessary. The composite component's own ID already enforces the uniqueness in the context of its parent naming container component. Opening the page in browser, rightclick-view source and observing the IDs in generated HTML output should already have given insights about that.
Just keep it simple:
<h:inputText ...>
<f:ajax ...render="table" />
</h:inputText>
<h:dataTable id="table" ...>
See also:
- How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
- Is it possible to update non-JSF components (plain HTML) with JSF ajax?
How Can I Use Ajax To Update A GraphicImage Without Blinking?
You could bind an onevent
attribute to your ajax tag:
<f:ajax render="productImage" listener="#{orderController.productSelectionChanged}"
onevent="ajaxEventListener"/>
Then, you get notified whenever some phase of the ajax process happens. You might be interested in implementing something like this with jQuery:
function ajaxEventListener(data) {
var status = data.status; // Can be "begin", "complete" or "success".
var source = data.source; // The parent HTML DOM element.
//Give your form an id in order to access the image in JS
var $image = $(document.getElementById("yourFormId:productImage")); //Grab your image
switch (status) {
case "begin": // Before the ajax request is sent.
// Fade out your image
$image.fadeOut( "slow" );
break;
case "success": // After update of HTML DOM based on ajax response.
// You've got the url properly updated, start fading in the image again
$image.fadeIn( "slow" );
break;
}
}
In order to improve loading times, you should read some papers about how to cache resources in the web browser. That's not JSF specific, though, it's something you could do with a web filter.
See also:
- Execute JavaScript before and after the f:ajax listener is invoked
- How to select JSF components using jQuery?
- http://api.jquery.com/fadeout/
- http://api.jquery.com/fadeIn/
Update preRenderView component with ajax
Use the preRenderComponent
event instead and put those f:events inside the divs.
I'm not sure if it will play nicely with this kind of JSF binding though. You may have to replace those divs with h:panelGroup layout="block"
(which renders simple divs as well).
Related Topics
Ellipsis For Overflow Text in Dropdown Boxes
Animate/Shrink Navbar on Scroll Using Bootstrap
Adding HTML Class Tag Under ≪Option≫ in Html.Dropdownlist
Firefox Linux (Centos) Responsive Design Image Scaling
How to Set the Max-Width of a Table Cell Using Percentages
Dynamically Adding and Removing Components in Angular
How to Make a Display:Flex Container Expand Horizontally with Its Wrapped Contents
Html5 Input Type Range Show Range Value
Where Is the HTML5 Document Type Definition
How to Correctly Select the First or the Last Child With Css
Javaserver Faces 2.2 and Html5 Support, Why Is Xhtml Still Being Used
Responsive CSS Trapezoid Shape
Font Awesome Icon Inside Text Input Element
How to Prevent a Browser from Storing Passwords