【问题标题】:Execute managebean method from javascript onload event从javascript onload事件执行managebean方法
【发布时间】:2011-07-28 05:16:28
【问题描述】:

如何发出一个 ajax 请求来从 javascript 更新 <h:dataTable>?我目前正在使用 @Postconstruct 加载初始数据,但这会显着延迟初始页面加载。

我正在考虑使用<body> HTML 标记的onload 事件来触发请求并更新数据表。

【问题讨论】:

    标签: java javascript jsf jsf-2


    【解决方案1】:

    在 jsf2.0 中,您几乎可以在任何其他 jsf 标签中使用 f:ajax 标签,例如

    <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>
    

    在本例中,someMethod 在 javasript onClick 事件中为“myComponent”selectOneRadio 执行

    不确定这是不是你想要的......

    【讨论】:

    • 谢谢,我希望在页面加载后自动发出请求
    • 也许 PreRenderViewEvent 可能会解决您的问题&lt;f:view .......&gt; &lt;f:event type="preRenderView" listener="#{someBean.download}"/&gt; &lt;/f:view&gt;
    • 但这不是异步的
    【解决方案2】:

    理论上以下应该做到这一点。

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

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

    但是,由于某种原因,这不受支持。我曾经为此发布过issue report

    以下内容有效,但本质上是一种 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>
    

    如果您碰巧使用 PrimeFaces,那么您可以将其 &lt;p:remoteCommand&gt;autoRun set to true 一起使用。

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

    或者,如果您使用的是 OmniFaces,那么您可以使用它的&lt;o:commandScript&gt;

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

    &lt;h:outputScript target="body"&gt;&lt;body&gt; 的末尾呈现&lt;script&gt;。即将推出的 OmniFaces 2.2 将通过 new autorun attribute 消除这一需求。

    <h:body>
        <h:form>
            <o:commandScript name="onload" action="#{bean.onload}" autorun="true" />
        </h:form>
    </h:body>
    

    【讨论】:

    • 理论上它应该可以工作。不起作用。但是隐藏的按钮就像魅力一样工作
    • primefaces 做到了这一点,即使是重定向(只需从操作方法返回您想要的页面)
    • @BalusC 我无法打开问题报告超链接。这个问题解决了吗?
    【解决方案3】:

    我通过使用元数据函数解决了这个问题,因为我无法使用@PostContruct(FacesMessages 被排入队列并且在 postconstruct mehtod 中抛出时不显示...see 最后评论)

    <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>
    

    我对 JSF 很陌生,所以... 我不太了解 JSF 的生命周期阶段,但这个解决方案对我有用。

    【讨论】:

    • 这不会在 JavaScript onload 事件期间运行。这远在网页从服务器发送到客户端之前运行。 OP 明确要求在 JavaScript onload 事件期间运行 bean 方法。 OP 不要求在 JSF 呈现响应阶段之前运行 bean 方法。