name: jsf-ajax description: > JSF AJAX update rules for the HMIS project. Use when working on AJAX updates, p:commandButton update attributes, PrimeFaces AJAX callbacks, partial page rendering, or debugging AJAX update failures. Also covers JSF navigation patterns: why f:viewAction must not be used on @SessionScoped beans, and how initialization belongs in navigation methods. Critical rules to prevent silent AJAX failures and refresh/back-button state corruption. user-invocable: true
JSF AJAX Update Guidelines
Critical Rules
- AJAX UPDATE RULE: NEVER use plain HTML elements (div, span) with id attributes for AJAX updates - use JSF components (
h:panelGroup,p:outputPanel) instead - RENDERED ATTRIBUTE RULE: NEVER use
renderedon plain HTML elements - JSF ignores it; useh:panelGroup layout="block"instead - COMPONENT REFERENCES: Use
p:resolveFirstComponentWithIdfor updates:update=":#{p:resolveFirstComponentWithId('componentId',view).clientId}" - NO CSS/jQuery SELECTORS: NEVER use
@(.class),@(#id),@parentinupdateorprocessattributes. Use@this,@form, explicit IDs, or:#{p:resolveFirstComponentWithId(...)}
Wrong vs Correct
<!-- WRONG - Plain HTML, AJAX silently fails -->
<div id="stockSelection">
<!-- content -->
</div>
<p:commandButton update="stockSelection" />
<!-- CORRECT - JSF component, AJAX works -->
<h:panelGroup id="stockSelection">
<div><!-- content --></div>
</h:panelGroup>
<p:commandButton update="stockSelection" />
Updating Growl/Messages
The growl component is in template.xhtml outside forms. Use absolute ID with colon prefix:
<!-- CORRECT -->
<p:commandButton action="#{bean.save}" update="myTable :growl" />
<!-- WRONG - Do NOT use CSS selectors -->
<p:commandButton update="@(.ui-growl)" />
JSF Components for AJAX Updates
h:panelGroup- Lightweight wrapper, no HTML outputp:outputPanel- PrimeFaces panel, renders as<span>or<div>h:div- Renders as HTML<div>h:form- For updating entire form sectionsp:panel- Full-featured panel with header/footer
Debugging
- Check browser console for JavaScript errors
- Verify target element is a JSF component (not plain HTML)
- Use browser dev tools to confirm JSF-generated id
- Test with
h:panelGroupwrapper if updates fail - Check component hierarchy - nested components affect id resolution
For complete reference, read developer_docs/jsf/ajax-update-guidelines.md.
PrimeFaces DataTable Multi-Selection (Current Syntax)
๐จ Do NOT use selectionMode="multiple" on <p:column> โ that is the PrimeFaces 7 and earlier pattern. The current PrimeFaces requires selectionMode on the dataTable and selectionBox="true" on the column.
Wrong (old PrimeFaces, no checkboxes render in current version)
<p:dataTable value="#{bean.items}" var="i"
selection="#{bean.selected}" rowKey="#{i.id}">
<p:column selectionMode="multiple" /> <!-- WRONG -->
...
</p:dataTable>
Correct (current PrimeFaces)
<p:dataTable value="#{bean.items}" var="i"
selection="#{bean.selected}" rowKey="#{i.id}"
selectionMode="multiple">
<p:column selectionBox="true" style="width: 3rem; text-align: center;" />
...
</p:dataTable>
Also: bind selection to an array (MyDTO[] selected), not a List. Always include rowKey.
For complete reference (single-selection, controller pattern, selectAllFilteredOnly, troubleshooting), read developer_docs/jsf/primefaces-datatable-selection.md.
Navigation Pattern: Never Use f:viewAction on @SessionScoped Beans
๐จ Most controllers in this project are @SessionScoped. Never use f:viewAction or f:event type="preRenderView" to initialize state on @SessionScoped beans.
f:viewAction fires on every GET โ including browser refresh and back-button โ silently resetting in-progress state. All initialization belongs in the navigation method that redirects to the page.
Correct pattern
// Navigation method โ initialize here
public String navigateToFundTransferBill() {
resetClassVariables();
prepareToAddNewFundTransferBill();
currentBillPayments = new ArrayList<>();
return "/cashier/fund_transfer_bill?faces-redirect=true";
}
<!-- XHTML โ no f:metadata needed -->
<ui:define name="subcontent">
<h:form>...</h:form>
</ui:define>
The two legitimate uses of f:viewAction
URL parameter ingestion โ page is reached via external URL with
f:viewParamquery params (lab result links, mobile API, patient portal). No navigation method exists; the URL is the entry point. Signal:f:metadatacontainsf:viewParamelements.@ViewScopedbeans โ bean is created fresh on each page load, so there is no prior navigation method. (Rare in this project โ most controllers are@SessionScoped.)
If you see f:viewAction without any f:viewParam, it is almost certainly wrong.
For complete reference, read developer_docs/jsf/navigation-patterns.md.