28

How can I make an ajax request that updates a <h:dataTable> from javascript? I am currently loading the initial data using @Postconstruct but that is significantly delaying the initial page load.

I am thinking about using onload event of <body> HTML tag to fire the request and update the datatable.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
Farouk Alhassan
  • 3,780
  • 9
  • 51
  • 74

3 Answers3

62

In theory the following should do it.

<h:body>
    <f:ajax event="load" listener="#{bean.onload}" />
</h:body>

with

public void onload(AjaxBehaviourEvent event) {
    // ...
}

However, this is not supported for some reason. I've ever posted an issue report about that.

The following works, but it's in essence a hack.

<h:head>
    <title>JSF 2.0 onload hack</title>
    <script>
        window.onload = function() {
            document.getElementById('hidden:link').onclick();
        }
    </script>
</h:head>
<h:body>
    <h:form id="hidden" style="display:none">
        <h:commandLink id="link">
            <f:ajax event="click" listener="#{bean.onload}" />
        </h:commandLink>
    </h:form>
</h:body>

If you happen to use PrimeFaces, then you can use its <p:remoteCommand> with autoRun set to true.

<h:body>
    <h:form>
        <p:remoteCommand name="onload" action="#{bean.onload}" autoRun="true" />
    </h:form>
</h:body>

Or if you're using OmniFaces, then you can use its <o:commandScript>

<h:body>
    <h:form>
        <o:commandScript name="onload" action="#{bean.onload}" />
        <h:outputScript target="body">onload()</h:outputScript>
    </h:form>
</h:body>

The <h:outputScript target="body"> renders the <script> in the end of the <body>. The upcoming OmniFaces 2.2 will remove this need by new autorun attribute.

<h:body>
    <h:form>
        <o:commandScript name="onload" action="#{bean.onload}" autorun="true" />
    </h:form>
</h:body>
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
1

in jsf2.0 you can use the f:ajax tag in almost any other jsf tag e.g

<h:selectOneRadio id="myComponent" value="#{someBean.inputMethod}">
<f:selectItem itemValue="#{someBean.A}" itemLabel="A" />
<f:selectItem itemValue="#{someBean.B}" itemLabel="B" />
       <f:ajax event="click" action=#{someBean.someMethod} />
</h:selectOneRadio>

In this example the someMethod is excuted in the javasript onClick event for the "myComponent" selectOneRadio

Not sure if this is what you are after ....

ChristiaanP
  • 655
  • 6
  • 20
-1

I solved it by using the Metadata-Functions, as I could not use @PostContruct (FacesMessages are enqueued and not displayed when thrown in postconstruct mehtod... see last comment)

<f:metadata>
<f:viewAction action="#{bean.initProducts}" />
</f:metadata>

<h:body>
<ui:composition template="/templates/commonTemplate.xhtml">

    <ui:define name="body">

        <h:panelGroup>
            <h:dataTable id="table"
                value="#{bean.getProducts}" var="product"

              <!-- Table Stuff-->
            </h:dataTable>
        </h:panelGroup>


    </ui:define>
</ui:composition>

I am very new to JSF so ... I DO NOT know very much about JSF's lifecycle phases, but this solution worked for me.

Niko
  • 23
  • 4
  • This doesn't run during JavaScript onload event. This runs far before the webpage is sent from server to client. OP is explicitly asking to run a bean method during JavaScript onload event. OP is not asking to run a bean method before the JSF render response phase. – BalusC Nov 21 '18 at 11:31