【问题标题】:Calling history.pushState on dataTable rowSelect在 dataTable rowSelect 上调用 history.pushState
【发布时间】:2015-05-02 23:58:26
【问题描述】:

我正在使用 PrimeFaces 5.1,当用户使用以下代码单击 p:dataTable 行时,我调用 history.pushState

<p:dataTable value="#{associateBean.scenarios}" 
        selectionMode="single"
        selection="#{associateBean.selectedScenarioViewBean}"
        var="scenarioViewBean" rowKey="#{scenarioViewBean.id}">
    <p:ajax event="rowSelect"
        listener="#{associateBean.onScenarioRowSelect}"
        oncomplete="history.pushState('','','test#{scenarioViewBean.id}')"
        update="@form"/>
    <p:column>
        <h:outputText value="#{scenarioViewBean.name}"/>
    </p:column>
</p:dataTable>

如您所见,我正在尝试将 scenarioViewBean.id 值传递给我的 pushState 调用。

问题在于#{scenarioViewBean.id} 不返回任何内容,因此 JavaScript 在 URL 中推送“test”而不是“test123”。

我该如何解决这个问题?

【问题讨论】:

    标签: javascript jsf primefaces datatable pushstate


    【解决方案1】:

    无需复杂化,保留 rowSelect ajax 事件并按如下方式传递 Id:

    PF('dataTableWV').selection[0]
    

    根据您的问题,最终结果应如下所示:

    <p:ajax event="rowSelect"
        listener="#{associateBean.onScenarioRowSelect}"
        oncomplete="history.pushState('','','test'+PF('dataTableWV').selection[0]"
        update="@form"/>
    

    注意:dataTableWV 是 dataTable widgetVar

    【讨论】:

    • 谢谢 Hatem,这个电话比我自己的回答简单得多,所以我接受了。然而,在p:ajax rowSelect 中直接使用pushState 存在一个缺陷:当我们编写popstate 事件处理程序时,我们不能再使用selectRow 方法,因为它会调用history.pushState,从而使“前进按钮” "消失(换句话说,popstate 事件不能调用pushState 方法)。
    • 我通常使用history.js,因为在某些情况下,某些浏览器存在回退兼容性,在您的情况下,它可能有助于避免导致问题的任何原因,它从来没有让我失望:)
    • 好的对不起,我们同时回答。 :)
    【解决方案2】:

    好的,现在可以了,但我必须调整 DataTable 组件:

    <script type="text/javascript">
    jQuery(document).ready(function(jQuery) {
        function updateHistory(selectedRowKey) {
            history.pushState({
                     selectedRowKey: selectedRowKey
                     },
                     document.title,
                     selectedRowKey);
        }
        if (PF('widgetScenariosDataTable')) {
            // initial callback
            var f = PF('widgetScenariosDataTable').onRowClick;
            PF('widgetScenariosDataTable').onRowClick = function(event, rowElement) {
                // Call initial callback (we have to use apply because
                // the method is using 'this')
                f.apply(PF('widgetScenariosDataTable'), [event, rowElement]);
                // selected row key
                var selectedRowKey = PF('widgetScenariosDataTable').selection;
                // Your callback
                updateHistory(selectedRowKey);
            };
            jQuery(window).bind('popstate', function(event) {
                // First we have to unselect all rows
                PF('widgetScenariosDataTable').unselectAllRows();
                if (event.originalEvent.state!=null) {
                    // We select the row by passing the tr object that
                    // has the correct rowKey value (this is safer than 
                    // using the rowIndex if the user adds/deletes the 
                    // datatable rows and then uses the browser's history)
                    PF('widgetScenariosDataTable').selectRow(
                        jQuery("tr[data-rk="+event.originalEvent.state.selectedScenarioId+"]"),
                        false
                    );
                }
                else {
                    // We use location.href if there is no state stored
                    var href = window.location.href;
                    PF('widgetScenariosDataTable').selectRow(
                            jQuery("tr[data-rk="+href.substr(href.lastIndexOf('/') + 1)+"]"),
                            false
                    );
                }
            });
        }
    });
    </script>
    

    此代码改编自http://www.takohi.com/javascript-callback-on-row-click-event-with-primefaces-datatable/

    如果有人知道更简单的方法,请发布,然后我会将您的答案添加为最佳答案。

    【讨论】:

      【解决方案3】:

      我的解决方案不使用 onRowClick 事件:

      <h:outputScript library="js" target="head" name="pop.js"/>
      
      <p:dataTable id="table" widgetVar="tableWdg" var="vv"
          value="#{bean.list}"
          rowKey="#{vv.id}" rowIndexVar="rowIndex"
          selectionMode="single"
          selection="#{bean.selected}">
      
          <p:ajax event="rowSelect" process="@this" listener="#{bean.actionRowSelect}"/>
      
          <p:column headerText="ID">
              <h:outputText value="#{vv.id}" />
          </p:column>
      </p:dataTable>
      

      “bean”中的侦听器:

       public void actionRowSelect(SelectEvent event) {
           SelectedElement element = (SelectedElement) event.getObject();
           HashMap<String, Object> jsonParams = new HashMap<String, Object>();
           jsonParams.put("selectedRow", element.getId());
           jsonParams.put("tableWdgName", table.getWidgetVar());
           JSONObject json = new JSONObject(jsonParams);
           String jsonString = json.toString();
           String title = "generate yourself";
           HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
           String url = req.getRequestURL().toString();
           if(req.getQueryString().length() > 0) {
               url += "?" + req.getQueryString();
           }
           String jscriptString = "if (popstated != true) { window.history.pushState(" + jsonString + ", '" + title + "', '" + url + "'); popstated = false; } " ;
           RequestContext.getCurrentInstance().execute(jscriptString);
      
       }
      

      还有 JS 脚本 'pop.js':

      var popstated = false;
      
      window.addEventListener('popstate', function(event) {
        console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
        console.log("event state.selectedRow=" + event.state.selectedRow);
        PF(tableWdgName).unselectAllRows();
        if(event.state.selectedRow != null) {
            popstated = true;
            PF(tableWdgName).selectRow(
                    jQuery( "tr[data-rk=" + event.state.selectedRow + "]" ),
                    false
                    );
        }
      });
      

      诀窍是简单的布尔全局 JS 变量 'popstated' 并在服务器端生成 JS。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-12
        • 1970-01-01
        • 2012-05-12
        • 2016-08-06
        • 1970-01-01
        • 2012-10-08
        • 2017-06-12
        相关资源
        最近更新 更多