✨ (base): Añade componente Pager
Incluye soporte HTMX vía `sort_link()`/`hx_pager` para navegación sin recarga.
This commit is contained in:
parent
e8bba0803d
commit
3b01894024
14 changed files with 881 additions and 31 deletions
|
|
@ -490,6 +490,13 @@ pub mod swap {
|
|||
pub const INNER_HTML: &str = "innerHTML";
|
||||
/// Reemplaza el elemento objetivo completo.
|
||||
pub const OUTER_HTML: &str = "outerHTML";
|
||||
/// Reemplaza el elemento objetivo completo y desplaza la vista al borde superior tras el
|
||||
/// intercambio (combina [`OUTER_HTML`] con el modificador `scroll:top`).
|
||||
///
|
||||
/// Pensado para listados paginados/ordenables cuyo `hx-swap` sustituye un contenedor completo
|
||||
/// (tabla + paginador) al variar el número de filas entre páginas. Sin este anclaje la posición
|
||||
/// del scroll tras el intercambio queda desajustada.
|
||||
pub const OUTER_HTML_SCROLL_TOP: &str = "outerHTML scroll:top";
|
||||
/// Inserta la respuesta antes de la etiqueta de apertura del objetivo.
|
||||
pub const BEFORE_BEGIN: &str = "beforebegin";
|
||||
/// Inserta la respuesta al inicio del contenido del objetivo.
|
||||
|
|
|
|||
32
extensions/pagetop-htmx/src/hx_pager.rs
Normal file
32
extensions/pagetop-htmx/src/hx_pager.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//! Soporte HTMX al componente [`Pager`].
|
||||
//!
|
||||
//! [`Pager`] no conoce HTMX ni ninguna otra librería de interactividad. Cada enlace de página ya
|
||||
//! funciona como una petición normal, y el elemento `<nav>` que los envuelve expone su propio
|
||||
//! [`Props`], accesible con [`with_prop()`], que admite cualquier atributo HTML por nombre y valor
|
||||
//! mediante [`PropsOp::set()`].
|
||||
//!
|
||||
//! Para una navegación sin recarga basta con añadir `hx::BOOST` (más `hx::TARGET` y `hx::SWAP`) al
|
||||
//! propio `<nav>`. HTMX convierte automáticamente en peticiones AJAX los enlaces de todas las
|
||||
//! páginas, reutilizando el `href` que cada uno ya tiene resuelto, sin que [`Pager`] tenga que
|
||||
//! generar ningún atributo `hx-*` por sí misma.
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use pagetop::prelude::*;
|
||||
//! use pagetop_htmx::prelude::*;
|
||||
//!
|
||||
//! let pager = Pager::new()
|
||||
//! .with_base_path("/admin/users")
|
||||
//! .with_extra_query("sort", "username")
|
||||
//! .with_current_page(2)
|
||||
//! .with_items_per_page(20)
|
||||
//! .with_total_items(97)
|
||||
//! .with_prop(PropsOp::set(hx::BOOST, "true"))
|
||||
//! .with_prop(PropsOp::set(hx::TARGET, "#user-table-wrapper"))
|
||||
//! .with_prop(PropsOp::set(hx::SWAP, hx::swap::OUTER_HTML_SCROLL_TOP))
|
||||
//! .with_prop(PropsOp::set(hx::PUSH_URL, "true"));
|
||||
//! ```
|
||||
//!
|
||||
//! [`Pager`]: pagetop::base::component::Pager
|
||||
//! [`Props`]: pagetop::html::Props
|
||||
//! [`PropsOp::set()`]: pagetop::html::PropsOp::set
|
||||
//! [`with_prop()`]: pagetop::base::component::Pager::with_prop
|
||||
|
|
@ -1,4 +1,17 @@
|
|||
//! Soporte HTMX al componente [`Table`].
|
||||
//!
|
||||
//! [`Table`] no conoce HTMX ni ninguna otra librería de interactividad. En su lugar, cada pieza que
|
||||
//! necesita comportamiento interactivo ([`table::Row`], [`table::Cell`], [`table::SortLink`])
|
||||
//! expone su propio [`Props`] que admite cualquier atributo HTML por nombre y valor mediante
|
||||
//! [`PropsOp::set()`], el mismo mecanismo que usa el resto de PageTop para adoptar HTMX sin
|
||||
//! depender de él. Basta con encadenar `.with_prop(PropsOp::set(hx::GET, ...))` sobre el elemento
|
||||
//! que corresponda.
|
||||
//!
|
||||
//! Las cabeceras ordenables ([`table::Column::with_sort`]) ya llevan resuelta la parte que no
|
||||
//! depende de HTMX: el enlace (`<a href>`), la semántica accesible (`aria-sort`) y el indicador
|
||||
//! visual de dirección (clases CSS). Sólo falta (si se quiere navegación sin recarga) añadir los
|
||||
//! atributos `hx-*` con [`table::SortLink::with_prop()`], o usar directamente [`sort_link()`] para
|
||||
//! no repetirlos en cada columna.
|
||||
|
||||
use pagetop::prelude::*;
|
||||
|
||||
|
|
@ -6,15 +19,13 @@ use crate::hx;
|
|||
|
||||
// **< sort_link() >********************************************************************************
|
||||
|
||||
/// Construye un [`SortLink`](pagetop::base::component::table::SortLink) para actualizar el orden de
|
||||
/// la tabla sin recargar la página.
|
||||
/// Construye un [`SortLink`] para actualizar el orden de la tabla sin recargar la página.
|
||||
///
|
||||
/// [`Table`] y `SortLink` no requieren HTMX. Cada extensión que quiera aplicar una navegación sin
|
||||
/// recarga debe añadir sus propios atributos `hx-*` usando
|
||||
/// [`SortLink::with_prop()`](pagetop::base::component::table::SortLink::with_prop). Como esos
|
||||
/// recarga debe añadir sus propios atributos `hx-*` usando [`SortLink::with_prop()`]. Como esos
|
||||
/// cuatro atributos son siempre los mismos para cualquier cabecera ordenable (`hx-get` igual al
|
||||
/// `href`, `hx-swap="outerHTML"` y `hx-push-url="true"`, y sólo `hx-target` cambia según la tabla),
|
||||
/// [`sort_link()`] evita reescribirlos en cada columna de cada listado.
|
||||
/// `href`, `hx-swap="outerHTML scroll:top"` y `hx-push-url="true"`, y sólo `hx-target` cambia según
|
||||
/// la tabla), [`sort_link()`] evita reescribirlos en cada columna de cada listado.
|
||||
///
|
||||
/// El enlace resultante funciona igual con o sin HTMX: `href` es siempre la URL real del nuevo
|
||||
/// estado de orden, así que navega correctamente aunque HTMX no esté disponible en el cliente.
|
||||
|
|
@ -23,13 +34,12 @@ use crate::hx;
|
|||
///
|
||||
/// - `href`: URL completa hacia el nuevo estado de orden, reflejando ya el campo y la dirección
|
||||
/// que resultarán de pulsar esta cabecera. Acepta cualquier tipo convertible a [`RoutePath`],
|
||||
/// normalmente el resultado de [`Context::route()`](pagetop::core::component::Context::route),
|
||||
/// para que el enlace preserve el parámetro `lang` cuando corresponda.
|
||||
/// normalmente el resultado de [`Context::route()`], para que el enlace preserve el parámetro
|
||||
/// `lang` cuando corresponda.
|
||||
/// - `target`: selector CSS del elemento que HTMX debe reemplazar (`hx-target`), típicamente el
|
||||
/// contenedor que envuelve la tabla completa.
|
||||
/// - `dir`: dirección de orden vigente de esta columna, o `None` si la tabla está ordenada
|
||||
/// actualmente por otra columna. Se traslada tal cual a
|
||||
/// [`SortLink::with_dir()`](pagetop::base::component::table::SortLink::with_dir).
|
||||
/// actualmente por otra columna. Se traslada tal cual a [`SortLink::with_dir()`].
|
||||
///
|
||||
/// # Ejemplo
|
||||
///
|
||||
|
|
@ -56,6 +66,11 @@ use crate::hx;
|
|||
/// .with_sort(hx_table::sort_link(href, "#user-table-wrapper", active))
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// [`SortLink`]: pagetop::base::component::table::SortLink
|
||||
/// [`SortLink::with_prop()`]: pagetop::base::component::table::SortLink::with_prop
|
||||
/// [`SortLink::with_dir()`]: pagetop::base::component::table::SortLink::with_dir
|
||||
/// [`Context::route()`]: pagetop::core::component::Context::route
|
||||
pub fn sort_link(
|
||||
href: impl Into<RoutePath>,
|
||||
target: impl AsRef<str>,
|
||||
|
|
@ -69,6 +84,6 @@ pub fn sort_link(
|
|||
.with_dir(dir)
|
||||
.with_prop(PropsOp::set(hx::GET, href))
|
||||
.with_prop(PropsOp::set(hx::TARGET, target))
|
||||
.with_prop(PropsOp::set(hx::SWAP, hx::swap::OUTER_HTML))
|
||||
.with_prop(PropsOp::set(hx::SWAP, hx::swap::OUTER_HTML_SCROLL_TOP))
|
||||
.with_prop(PropsOp::set(hx::PUSH_URL, "true"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ use pagetop::prelude::*;
|
|||
include_locales!(LOCALES_HTMX);
|
||||
|
||||
pub mod hx;
|
||||
pub mod hx_pager;
|
||||
pub mod hx_table;
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
|
|
@ -99,6 +100,7 @@ pub mod response;
|
|||
/// Prelude de `pagetop-htmx`.
|
||||
pub mod prelude {
|
||||
pub use crate::hx;
|
||||
pub use crate::hx_pager;
|
||||
pub use crate::hx_table;
|
||||
pub use crate::request::HtmxRequestExt;
|
||||
pub use crate::response::HtmxResponse;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue