Severity: medium — same audience as #2715 (Bootstrap-styled 3.x apps). Forces a regex hack in every app's pagination helper.
Surfaced by: titan Phase 2.4 (Wheels 4.0 upgrade), 2026-05-15.
Description
The Bootstrap pagination pattern places the active-page class on the <li> wrapper, not on the <a>:
<ul class=\"pagination\">
<li class=\"page-item\"><a class=\"page-link\" href=\"...\">1</a></li>
<li class=\"page-item active\"><a class=\"page-link\" href=\"...\">2</a></li>
<li class=\"page-item\"><a class=\"page-link\" href=\"...\">3</a></li>
</ul>
Neither paginationLinks() (legacy) nor pageNumberLinks() (4.0 primitive used internally by paginationNav()) can emit this. Both put classForCurrent on the <a>:
<li class=\"page-item\"><a class=\"page-link active\" href=\"...\">2</a></li>
The legacy addActiveClassToPrependedParent arg sounds like it should help, but it only inserts the class into the wrapper's existing class attribute; it doesn't replace the active on the anchor. Apps still need a Replace() regex post-process to move the class from <a> to <li>.
Titan's working pattern (in app/views/helpers.cfm after Phase 2.4 migration) keeps a Replace() hack across the bsPaginationLinks() output:
local.rv = Replace(local.rv, \" active\", \"\", \"all\"); // strip from anchors
// ... then re-insert into <li> via different code path
Suggested fix
Add to pageNumberLinks() (and inherited by paginationNav()) one of:
activeClassOnPrependedParent — if true, omit classForCurrent from the anchor, append it to prependToPage's class attribute on the current-page iteration only.
currentPageWrap=\"<li class='page-item active'><a class='page-link'>\" — full override on the current page, regardless of normal prependToPage.
Either lets Bootstrap-styled apps drop the regex hack.
cc @bpamiri
Severity: medium — same audience as #2715 (Bootstrap-styled 3.x apps). Forces a regex hack in every app's pagination helper.
Surfaced by: titan Phase 2.4 (Wheels 4.0 upgrade), 2026-05-15.
Description
The Bootstrap pagination pattern places the active-page class on the
<li>wrapper, not on the<a>:Neither
paginationLinks()(legacy) norpageNumberLinks()(4.0 primitive used internally bypaginationNav()) can emit this. Both putclassForCurrenton the<a>:The legacy
addActiveClassToPrependedParentarg sounds like it should help, but it only inserts the class into the wrapper's existingclassattribute; it doesn't replace theactiveon the anchor. Apps still need aReplace()regex post-process to move the class from<a>to<li>.Titan's working pattern (in
app/views/helpers.cfmafter Phase 2.4 migration) keeps aReplace()hack across thebsPaginationLinks()output:local.rv = Replace(local.rv, \" active\", \"\", \"all\"); // strip from anchors // ... then re-insert into <li> via different code pathSuggested fix
Add to
pageNumberLinks()(and inherited bypaginationNav()) one of:activeClassOnPrependedParent— if true, omitclassForCurrentfrom the anchor, append it toprependToPage's class attribute on the current-page iteration only.currentPageWrap=\"<li class='page-item active'><a class='page-link'>\"— full override on the current page, regardless of normalprependToPage.Either lets Bootstrap-styled apps drop the regex hack.
cc @bpamiri