在 dataTable rowSelect 上调用 history.pushState

Calling history.pushState on dataTable rowSelect

我正在使用 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} 没有 return 任何东西,所以 JavaScript 推 "test" 而不是 "test123" 在 URL.

我该如何解决这个问题?

好的,现在可以了,但我必须调整 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/

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

无需复杂化,保留您的 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

我不使用 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。