Añade ComponentError con HTML alternativo

`prepare_component()` ahora devuelve `Result<Markup, ComponentError>` en
lugar de `Markup`, para que los componentes señalen fallos durante el
renderizado de forma explícita.

`ComponentError` encapsula un mensaje de error y un marcado HTML
alternativo opcional (`fallback`). Si se produce un error, el ciclo de
renderizado registra la traza y muestra el `fallback` en lugar del
componente fallido, sin interrumpir el resto de la página.

Lo mismo aplica a los errores devueltos por la acción `PrepareRender` de
los temas, que siguen el mismo mecanismo.
This commit is contained in:
Manuel Cillero 2026-03-21 13:15:39 +01:00
parent a0b14aec36
commit 34aeeab2d7
26 changed files with 232 additions and 100 deletions

View file

@ -52,12 +52,12 @@ impl Component for Form {
self.alter_classes(ClassesOp::Prepend, "form");
}
fn prepare_component(&self, cx: &mut Context) -> Markup {
fn prepare_component(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
let method = match self.method() {
form::Method::Post => Some("post"),
form::Method::Get => None,
};
html! {
Ok(html! {
form
id=[self.id()]
class=[self.classes().get()]
@ -67,7 +67,7 @@ impl Component for Form {
{
(self.children().render(cx))
}
}
})
}
}

View file

@ -22,15 +22,15 @@ impl Component for Fieldset {
self.id.get()
}
fn prepare_component(&self, cx: &mut Context) -> Markup {
html! {
fn prepare_component(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
Ok(html! {
fieldset id=[self.id()] class=[self.classes().get()] disabled[*self.disabled()] {
@if let Some(legend) = self.legend().lookup(cx) {
legend { (legend) }
}
(self.children().render(cx))
}
}
})
}
}

View file

@ -36,9 +36,9 @@ impl Component for Input {
);
}
fn prepare_component(&self, cx: &mut Context) -> Markup {
fn prepare_component(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
let id = self.name().get().map(|name| util::join!("edit-", name));
html! {
Ok(html! {
div class=[self.classes().get()] {
@if let Some(label) = self.label().lookup(cx) {
label for=[&id] class="form-label" {
@ -72,7 +72,7 @@ impl Component for Input {
div class="form-text" { (description) }
}
}
}
})
}
}