没有在a4j上调用的动作:带内部a4j的commandButton:支持onclick事件

时间:2012-06-27 09:37:02

标签: richfaces jsf-1.2

我正在使用 JSF 1.2 RichFaces 3.3.3 。我在使用Twitter Bootstrap设计的页面上工作。我需要对这样的订单处理一个动作:

  1. 用户点击页面上的操作按钮
  2. 打开一个模态对话框并要求用户确认操作(如果用户取消操作,过程当然在这里结束),
  3. 在确认的情况下,对话框的内容从确认文本变为其他内容以跟随动作处理(在某些情况下显示进度条,例如,在代码中只是等待文本),< / LI>
  4. 操作完成后,对话框消失。
  5. 所以我需要在同一时间做两件事,交替对话框内容并在页面bean中启动一个动作。今天,我能够改变对话框内容,但是不会处理在我的bean中启动的动作...... 要做到这一点,我在我的bean中使用一个标志来切换对话框内容,由a4j:support onclick(在正常调用之前执行)修改,执行动作的a4j:commandButton。

    <a4j:commandButton 
        type="button"
        value="#{common.COMMON_Confirm}"
        styleClass="btn btn-danger"
        action="#{orderDetailBean.cancelOrder}"
        oncomplete="showCancelOrderModal(false);">
        <a4j:support 
            event="onclick" 
            actionListener="#{orderDetailBean.startProcessingMainAction}"
            reRender="cancelOrderForm" />
    </a4j:commandButton>
    

    也许这种做法是错误的...... 我成功地完成了这项工作!现在我花了很多时间让它再次运作,一些帮助应该是伟大的。请注意,我几个星期后自己学习JSF和RichFaces。

    现在,代码。

    在我的网页的一些代码下面,首先是启动流程的按钮(通过javascript函数打开对话框),然后是Twitter Bootstrap对话框本身。

    <!-- Main action button -->
    <h:form>
        <a4j:commandButton 
            id="cancelOrder"
            styleClass="btn btn-danger btn-large"
            style="width: 100%; margin-bottom: 7px;"
            value="#{app.ACTION_OrderCancel}"
            oncomplete="showCancelOrderModal(true);"
            reRender="cancelOrderForm" />
    </h:form>
    
    <script type="text/javascript">
        function showCancelOrderModal(visible) {
            jQuery( function($) {
                $('#cancelOrderModal').modal(visible ? 'show' : 'hide');
            });
        }
    </script>
    
    <!-- Cancel order modal -->
    <div class="modal modal-narrow modal-small hide fade" id="cancelOrderModal">
        <div class="modal-header">
            <h3>
                <h:outputText value="#{app.MODAL_CancelOrderTitle}" />
            </h3>
        </div>
        <a4j:form id="cancelOrderForm">
            <a4j:outputPanel 
                id="cancelOrderConfirm"
                rendered="#{!orderDetailBean.processingAction}">
                <div class="modal-body">
                    <p>
                        <h:outputText value="#{app.MODAL_CancelOrderConfirm}" />
                    </p>
                </div>
                <div class="modal-footer">
                    <a href="#" 
                        class="btn btn-primary" 
                        data-dismiss="modal">
                        #{common.COMMON_Cancel}
                    </a>
                    <a4j:commandButton 
                        type="button"
                        value="#{common.COMMON_Confirm}"
                        styleClass="btn btn-danger"
                        action="#{orderDetailBean.cancelOrder}"
                        oncomplete="showCancelOrderModal(false);">
                        <a4j:support 
                            event="onclick" 
                            actionListener="#{orderDetailBean.startProcessingMainAction}"
                            reRender="cancelOrderForm" />
                    </a4j:commandButton>
                </div>
            </a4j:outputPanel>
            <a4j:outputPanel 
                id="cancelOrderWait"
                rendered="#{orderDetailBean.processingAction}">
                <div class="modal-body">
                    <h:outputText value="#{app.MODAL_CancelWait}" />
                </div>
            </a4j:outputPanel>
            <a4j:poll 
                id="cancelOrderPoll"
                interval="1000"
                enabled="#{orderDetailBean.processingAction}"
                reRender="cancelOrderPoll, cancelOrderWait" />
        </a4j:form>
    </div>
    

    我的bean中的代码

    private boolean processingAction;
    
    public void startProcessingMainAction(ActionEvent event) {
        logger.debug("Set processing order main action to TRUE");
        processingAction = true;
    }
    
    public String cancelOrder() {
        logger.debug("Start to cancel order with id " + order.getId());
        try {
            processingAction = true;
            cancelProductionOrder(order.getId());
        }
        catch (Exception e) {
            logger.error("Unable to cancel production order" + order.getId(), e);
            addErrorMessage("An error occured cancelling order: " + e.getMessage(), null);
            return "error";
        }
        finally {
            processingAction = false;
        }
        return "";
    }
    

    那么,执行时会发生什么?

    对话框正在打开,用户确认后对话框内容交替显示(所以a4j:支持效果很好),但由于未调用a4j:commandButton操作,其oncomplete将立即执行,对话框消失。

    我希望你能帮助我,这是我用户界面的一个重要部分,截止日期是在本周末^ _ ^


    更新我观察到随机行为。很少(现在是2次),但有时,一切正常,99%命令按钮的动作没有被调用:/

1 个答案:

答案 0 :(得分:1)

<a4j:support>操作完成后,您将重新呈现整个表单。这样,表单的HTML DOM树将被删除并替换为ajax响应中的一个。这几乎与需要执行<a4j:commandButton>的默认操作的同时发生。这里有竞争条件。如果之前发生默认操作将被执行,那么它将永远不会被执行,因为源已完全消失。

具体的功能要求并不完全清楚,因为startProcessingMainAction()在给定的例子中没有意义,它似乎完全是多余的。但我认为您可以通过将reRender属性从<a4j:support>移动到<a4j:commandButton>来解决此问题,以便仅在默认操作完成时重新呈现它。或者甚至更好,只需完全删除<a4j:support>,您根本不需要它。