PrimeFaces 分页器 JumpToPageDropdown 错误

PrimeFaces Paginator JumpToPageDropdown Bug

我正在从 PrimeFaces 6.2 迁移到 8.0。在我的项目中,我使用了多个 Primeface DataTables with a Paginator.

MCVE:

创建一个包含 10 个以上元素的数据列表。然后单击不同的页码。当从 JumpToPageDropdown 中单击或选择任何大于 10 的页码时,控制台将记录以下错误:

Chrome 控制台出错:

jquery.js.xhtml?ln=primefaces&v=8.0:2 Uncaught Error: Syntax error, unrecognized expression: option[value= 0]
    at Function.se.error (jquery.js.xhtml?ln=primefaces&v=8.0:2)
    at se.tokenize (jquery.js.xhtml?ln=primefaces&v=8.0:2)
    at se.compile (jquery.js.xhtml?ln=primefaces&v=8.0:2)
    at se.select (jquery.js.xhtml?ln=primefaces&v=8.0:2)
    at se (jquery.js.xhtml?ln=primefaces&v=8.0:2)
    at Function.se.matches (jquery.js.xhtml?ln=primefaces&v=8.0:2)
    at Function.k.filter (jquery.js.xhtml?ln=primefaces&v=8.0:2)
    at k.fn.init.k.fn.<computed> [as children] (jquery.js.xhtml?ln=primefaces&v=8.0:2)
    at c.updateUI (components.js.xhtml?ln=primefaces&v=8.0:58)
    at c.updateTotalRecords (components.js.xhtml?ln=primefaces&v=8.0:58)

使用的组件:

<p:dataTable id="datatable"value="#{backendController.dataList}"
    var="data" paginator="true" rows="1" paginatorPosition="top"
    pageLinks="20"
    paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {JumpToPageDropdown} {NextPageLink} {LastPageLink}">

    -> Add a few <p:column> tags.        

</p:dataTable>

临时修复:

我能够确定 JumpToPageDropdown 是导致错误的原因。当它从 paginatorTemplate 中删除时,单击大于 10 的页面时将不再显示错误。不幸的是我想使用这个下拉列表。

进一步研究:

PrimeFaces 将这些 JS 文件用于其组件,因此也用于 JumpToPageDropdown:

这是更新

的相应调用
Both versions:
this.jtpSelect = this.jq.children(".ui-paginator-jtp-select");

PrimeFaces 8.0:
this.jtpSelect.children("option[value=" + $.escapeSelector(this.cfg.page) + "]").prop("selected", "selected")

PrimeFaces 6.2:
this.jtpSelect.children("option[value=" + (this.cfg.page) + "]").prop("selected", "selected")

不同的是在8.0版本中this.cfg.page的值被传递给函数$.escapeSelector().

this.cfg.page 使用从零开始的编号。第 1 页为 0,第 10 页为 9,依此类推。在版本 6.2 中,当所选页面为 11 时,this.jtpSelect.children() 将使用选项 [value=10] 调用。但在版本 8.0 中,$.escapeSelector() 会将相同的输入格式化为 0 并导致 option[value= 0].

这导致了上述错误。看到这一行:Uncaught Error: Syntax error, unrecognized expression: option[value= 0]

建议:

如果这是一个错误 $.escapeSelector() 应该从 PrimeFaces 8.0 中的这个函数中删除,显然不需要转义:数字不需要转义。

解决方法:

深入研究代码后,我发现了修复错误的技巧:

window.PrimeFaces.widget.Paginator.prototype.updateUI = function(){
    if (this.cfg.page === 0) {
        this.disableElement(this.firstLink);
        this.disableElement(this.prevLink)
    } else {
        this.enableElement(this.firstLink);
        this.enableElement(this.prevLink)
    }
    if (this.cfg.page === (this.cfg.pageCount - 1)) {
        this.disableElement(this.nextLink);
        this.disableElement(this.endLink)
    } else {
        this.enableElement(this.nextLink);
        this.enableElement(this.endLink)
    }
    var a = (this.cfg.rowCount === 0) ? 0 : (this.cfg.page * this.cfg.rows) + 1
      , c = (this.cfg.page * this.cfg.rows) + this.cfg.rows;
    if (c > this.cfg.rowCount) {
        c = this.cfg.rowCount
    }
    var e = this.cfg.currentPageTemplate.replace("{currentPage}", this.cfg.page + 1).replace("{totalPages}", this.cfg.pageCount).replace("{totalRecords}", this.cfg.rowCount).replace("{startRecord}", a).replace("{endRecord}", c);
    this.currentReport.text(e);
    if (this.cfg.prevRows !== this.cfg.rows) {
        this.rppSelect.filter(":not(.ui-state-focus)").children("option").filter('option[value="' + $.escapeSelector(this.cfg.rows) + '"]').prop("selected", true);
        this.cfg.prevRows = this.cfg.rows
    }
    if (this.jtpSelect.length > 0) {
        if (this.jtpSelect[0].options.length != this.cfg.pageCount) {
            var d = "";
            for (var b = 0; b < this.cfg.pageCount; b++) {
                d += '<option value="' + b + '">' + (b + 1) + "</option>"
            }
            this.jtpSelect.html(d)
        }
        this.jtpSelect.children("option[value=" + (this.cfg.page) + "]").prop("selected", "selected")
    }
    if (this.jtpInput.length > 0) {
        this.jtpInput.val(this.cfg.page + 1)
    }
    this.updatePageLinks()
}

解释:

Paginator widget 的updateUI 函数导致错误。它可以通过 window.PrimeFaces.widget.Paginator.prototype.updateUI 访问,然后被更正后的版本覆盖。

hack 中更改的行:

this.jtpSelect.children("option[value=" + (this.cfg.page) + "]").prop("selected", "selected")

PrimeFaces 8.0 中的原始行:

this.jtpSelect.children("option[value=" + $.escapeSelector(this.cfg.page) + "]").prop("selected", "selected").