Skip to content

fix(ui): reinit Alpine.js on OOB-swapped pagination controls after fi…#3206

Merged
crivetimihai merged 4 commits intomainfrom
fix/pagination-filter-display
Mar 19, 2026
Merged

fix(ui): reinit Alpine.js on OOB-swapped pagination controls after fi…#3206
crivetimihai merged 4 commits intomainfrom
fix/pagination-filter-display

Conversation

@crivetimihai
Copy link
Member

Note: This PR was re-created from #3047 due to repository maintenance. Your code and branch are intact. @omorros please verify everything looks good.

🔗 Related Issue
Closes #3039


📝 Summary

When filtering/searching table items in the admin panel, pagination controls (page info text, navigation buttons) were not
rendering. This was caused by two issues:

  1. Alpine.js not reinitializing after HTMX OOB swaps, When loadSearchablePanel() fires htmx.ajax(), the response OOB-swaps
    the pagination controls div, but Alpine.js's MutationObserver doesn't reliably detect and initialize the new x-data
    component. Added an htmx:afterSettle listener that explicitly calls Alpine.initTree() on uninitialized pagination controls.
  2. Wrong swap style, pagination_controls.html defaults hx_swap to innerHTML, but partial templates return full
    elements, causing nested tables with duplicate IDs. Set hx_swap = 'outerHTML' across all partial templates and initial
    renders in admin.html.

    🏷️ Type of Change

    • Bug fix
    • Feature / Enhancement
    • Documentation
    • Refactor
    • Chore (deps, CI, tooling)
    • Other (describe below)

    🧪 Verification

    ┌────────────────┬───────────────┬────────┐
    │ Check │ Command │ Status │
    ├────────────────┼───────────────┼────────┤
    │ Lint suite │ make lint │ │
    ├────────────────┼───────────────┼────────┤
    │ Unit tests │ make test │ │
    ├────────────────┼───────────────┼────────┤
    │ Coverage ≥ 80% │ make coverage │ │
    └────────────────┴───────────────┴────────┘


    ✅ Checklist

    • Code formatted (make black isort pre-commit)
    • Tests added/updated for changes
    • Documentation updated (if applicable)
    • No secrets or credentials committed

    📓 Notes (optional)

    Files changed:

    • mcpgateway/static/admin.js — Added Alpine.js reinitialization listener for pagination controls after HTMX settles
    • mcpgateway/templates/admin.html — Set hx_swap = 'outerHTML' for 5 initial pagination renders
    • 7 partial templates (tools, servers, resources, prompts, gateways, agents, tokens) — Added {% set hx_swap = 'outerHTML' %}
      (matching existing pattern in users_partial.html)

    Screenshots:
    Screenshot 2026-02-18 200323
    Screenshot 2026-02-18 200333

@crivetimihai crivetimihai added this to the Release 1.0.0-GA milestone Feb 24, 2026
@crivetimihai crivetimihai added bug Something isn't working ui User Interface SHOULD P2: Important but not vital; high-value items that are not crucial for the immediate release labels Feb 24, 2026
@omorros
Copy link
Contributor

omorros commented Feb 24, 2026

Hi @crivetimihai thanks for reopening this! I've verified the code, everything looks good, intact and matching my original changes. Ready for review whenever you get the chance. Thanks!

marekdano
marekdano previously approved these changes Feb 25, 2026
Copy link
Collaborator

@marekdano marekdano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirm that all changes are the same compared to #3047

LGTM 🚀

@crivetimihai crivetimihai added the merge-queue Rebased and ready to merge label Mar 3, 2026
@marekdano marekdano added the release-fix Critical bugfix required for the release label Mar 11, 2026
omorros and others added 4 commits March 19, 2026 21:19
…ltering

Closes #3039

Signed-off-by: Oriol Morros Vilaseca <OM368@student.aru.ac.uk>
Signed-off-by: Oriol Morros Vilaseca <OM368@student.aru.ac.uk>
- Add {% set hx_swap = 'outerHTML' %} to teams_partial.html OOB
  pagination controls, matching the pattern in all other partials
- Add 7 unit tests for Alpine.js reinitialization on OOB-swapped
  pagination controls covering: uninitialized, already-initialized,
  multiple controls, Alpine not loaded, initTree missing, no x-data
  child, and toggle coexistence

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
Change querySelectorAll selector from [id$="-pagination-controls"] to
[id*="-pagination-controls"] so it also matches metrics top-performers
IDs like "top-tools-pagination-controls-visible" which contain but
don't end with "-pagination-controls".

Add test for the metrics ID pattern.

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
@crivetimihai
Copy link
Member Author

Rebased onto main (clean, no conflicts) and reviewed.

Changes I made during review:

  1. teams_partial.html — Added missing {% set hx_swap = 'outerHTML' %} to OOB pagination controls. This was the only partial with OOB pagination that lacked the fix — all 10 partials are now consistent.

  2. admin.js — Broadened the Alpine reinit selector from [id$="-pagination-controls"] (ends-with) to [id*="-pagination-controls"] (contains). The original selector missed the metrics top-performers pagination controls whose IDs follow the pattern top-{entity}-pagination-controls-visible.

  3. admin-pagination.test.js — Added 8 unit tests for the Alpine.js reinit logic:

    • Calls initTree on uninitialized pagination controls
    • Skips already-initialized controls
    • Handles multiple controls (only inits uninitialized ones)
    • No error when Alpine is not loaded
    • No error when Alpine.initTree is not a function
    • No action when pagination div has no x-data child
    • Matches metrics top-*-pagination-controls-visible IDs
    • Toggle re-enabling still works alongside Alpine reinit

All 70 JS tests pass.

Copy link
Member Author

@crivetimihai crivetimihai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed and ready to merge. The fix correctly addresses both root causes (Alpine.js reinit race and wrong swap style). Added missing teams_partial fix, broadened selector to cover metrics pagination, and added comprehensive test coverage (70 tests passing).

@crivetimihai crivetimihai merged commit 494262e into main Mar 19, 2026
49 of 91 checks passed
@crivetimihai crivetimihai deleted the fix/pagination-filter-display branch March 19, 2026 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working merge-queue Rebased and ready to merge release-fix Critical bugfix required for the release SHOULD P2: Important but not vital; high-value items that are not crucial for the immediate release ui User Interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG][UI]: Pagination controls break when search/filter returns results with query parameters

3 participants