♻️ (pagetop): Sustituye Attr<T> por Option<T>
`Attr<T>` no aportaba nada sobre `Option<T>` directo: `Getters` ya trata los campos `Option<T>` como caso especial (`Option<&T>`, o `Option<T>` con `#[getters(copy)]`) y `#[builder_fn]` funciona igual sobre ellos.
This commit is contained in:
parent
213aa18b12
commit
bf4c635e59
21 changed files with 171 additions and 245 deletions
|
|
@ -102,8 +102,8 @@ impl Component for Button {
|
|||
button
|
||||
type=(self.kind())
|
||||
(self.props())
|
||||
name=[self.name().get()]
|
||||
value=[self.value().get()]
|
||||
name=[self.name().as_deref()]
|
||||
value=[self.value().as_deref()]
|
||||
title=[self.title().lookup(cx)]
|
||||
autofocus[*self.autofocus()]
|
||||
disabled[*self.disabled()]
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ impl Component for Field {
|
|||
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
// En `setup()` se garantiza que `name` e `id` están definidos antes del renderizado.
|
||||
let name = self.name().get().unwrap();
|
||||
let name = self.name().as_deref().unwrap();
|
||||
let container_id = self.id().unwrap();
|
||||
|
||||
Ok(html! {
|
||||
|
|
@ -162,8 +162,8 @@ impl Component for Field {
|
|||
type="checkbox"
|
||||
id=(&item_id)
|
||||
class="form-check-input"
|
||||
name=(&name)
|
||||
value=[item.value().get()]
|
||||
name=(name)
|
||||
value=[item.value().as_deref()]
|
||||
checked[*item.checked()]
|
||||
disabled[*item.disabled() || *self.disabled()];
|
||||
label class="form-check-label" for=(&item_id) {
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ impl Component for Checkbox {
|
|||
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
// En `setup()` se garantiza que `name` e `id` están definidos antes del renderizado.
|
||||
let name = self.name().get().unwrap();
|
||||
let name = self.name().as_deref().unwrap();
|
||||
let container_id = self.id().unwrap();
|
||||
|
||||
let checkbox_id = util::join!(&container_id, "-checkbox");
|
||||
|
|
@ -111,7 +111,7 @@ impl Component for Checkbox {
|
|||
role=[is_switch.then_some("switch")]
|
||||
id=(&checkbox_id)
|
||||
class="form-check-input"
|
||||
name=(&name)
|
||||
name=(name)
|
||||
value="true"
|
||||
checked[*self.checked()]
|
||||
autofocus[*self.autofocus()]
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ impl Component for Form {
|
|||
(self.props())
|
||||
action=[self.action().try_resolve(cx)]
|
||||
method=[method]
|
||||
accept-charset=[self.charset().get()]
|
||||
accept-charset=[self.charset().as_deref()]
|
||||
{
|
||||
(self.children().render(cx).await)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ impl Component for Hidden {
|
|||
Ok(html! {
|
||||
input
|
||||
type="hidden"
|
||||
name=[self.name().get()]
|
||||
value=[self.value().get()];
|
||||
name=[self.name().as_deref()]
|
||||
value=[self.value().as_deref()];
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,13 +165,15 @@ pub struct Field {
|
|||
/// Devuelve el texto de ayuda del campo.
|
||||
help_text: Lc,
|
||||
/// Devuelve la longitud mínima permitida en caracteres.
|
||||
minlength: Attr<u16>,
|
||||
#[getters(copy)]
|
||||
minlength: Option<u16>,
|
||||
/// Devuelve la longitud máxima permitida en caracteres.
|
||||
maxlength: Attr<u16>,
|
||||
#[getters(copy)]
|
||||
maxlength: Option<u16>,
|
||||
/// Devuelve el texto indicativo del campo.
|
||||
placeholder: Lc,
|
||||
/// Devuelve la configuración de autocompletado del campo.
|
||||
autocomplete: Attr<form::Autocomplete>,
|
||||
autocomplete: Option<form::Autocomplete>,
|
||||
/// Devuelve si el campo recibe el foco automáticamente al cargar la página.
|
||||
autofocus: bool,
|
||||
/// Devuelve si el campo es de sólo lectura.
|
||||
|
|
@ -183,7 +185,8 @@ pub struct Field {
|
|||
/// Devuelve si el campo se muestra como texto plano sin bordes ni fondo.
|
||||
plaintext: bool,
|
||||
/// Devuelve la sugerencia de teclado virtual para el campo.
|
||||
inputmode: Attr<Mode>,
|
||||
#[getters(copy)]
|
||||
inputmode: Option<Mode>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
|
@ -199,7 +202,7 @@ impl Component for Field {
|
|||
fn setup(&mut self, _cx: &Context) {
|
||||
if let Some(container_id) = self
|
||||
.id()
|
||||
.or_else(|| self.name().get().map(|n| util::join!("edit-", n)))
|
||||
.or_else(|| self.name().as_deref().map(|n| util::join!("edit-", n)))
|
||||
{
|
||||
self.alter_prop(PropsOp::ensure_id(container_id));
|
||||
}
|
||||
|
|
@ -225,9 +228,9 @@ impl Component for Field {
|
|||
let strict = self.kind().is_strict();
|
||||
let masked = *self.kind() == Kind::StrictPassword;
|
||||
let autocomplete = if strict {
|
||||
Some(form::Autocomplete::Off)
|
||||
Some(&form::Autocomplete::Off)
|
||||
} else {
|
||||
self.autocomplete().get()
|
||||
self.autocomplete()
|
||||
};
|
||||
|
||||
Ok(html! {
|
||||
|
|
@ -249,12 +252,12 @@ impl Component for Field {
|
|||
type=(self.kind())
|
||||
id=[input_id.as_deref()]
|
||||
class=(input_class)
|
||||
name=[self.name().get()]
|
||||
value=[self.value().get()]
|
||||
minlength=[self.minlength().get()]
|
||||
maxlength=[self.maxlength().get()]
|
||||
name=[self.name().as_deref()]
|
||||
value=[self.value().as_deref()]
|
||||
minlength=[self.minlength()]
|
||||
maxlength=[self.maxlength()]
|
||||
placeholder=[self.placeholder().lookup(cx)]
|
||||
inputmode=[self.inputmode().get()]
|
||||
inputmode=[self.inputmode()]
|
||||
autocomplete=[autocomplete]
|
||||
spellcheck=[strict.then_some("false")]
|
||||
autocorrect=[strict.then_some("off")]
|
||||
|
|
@ -434,15 +437,15 @@ impl Field {
|
|||
|
||||
/// Establece la longitud mínima permitida en caracteres (`None` para no imponer mínimo).
|
||||
#[builder_fn]
|
||||
pub fn with_minlength(mut self, minlength: Option<u16>) -> Self {
|
||||
self.minlength.alter_opt(minlength);
|
||||
pub fn with_minlength(mut self, minlength: impl Into<Option<u16>>) -> Self {
|
||||
self.minlength = minlength.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece la longitud máxima permitida en caracteres (`None` para no imponer límite).
|
||||
#[builder_fn]
|
||||
pub fn with_maxlength(mut self, maxlength: Option<u16>) -> Self {
|
||||
self.maxlength.alter_opt(maxlength);
|
||||
pub fn with_maxlength(mut self, maxlength: impl Into<Option<u16>>) -> Self {
|
||||
self.maxlength = maxlength.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -462,8 +465,11 @@ impl Field {
|
|||
/// [`Autocomplete::email()`](form::Autocomplete::email) o
|
||||
/// [`Autocomplete::current_password()`](form::Autocomplete::current_password)).
|
||||
#[builder_fn]
|
||||
pub fn with_autocomplete(mut self, autocomplete: Option<form::Autocomplete>) -> Self {
|
||||
self.autocomplete.alter_opt(autocomplete);
|
||||
pub fn with_autocomplete(
|
||||
mut self,
|
||||
autocomplete: impl Into<Option<form::Autocomplete>>,
|
||||
) -> Self {
|
||||
self.autocomplete = autocomplete.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -510,8 +516,8 @@ impl Field {
|
|||
/// A diferencia del atributo `type` ([`form::input::Kind`]), no restringe los valores aceptados
|
||||
/// ni activa la validación del navegador; es sólo una sugerencia de presentación.
|
||||
#[builder_fn]
|
||||
pub fn with_inputmode(mut self, inputmode: Option<Mode>) -> Self {
|
||||
self.inputmode.alter_opt(inputmode);
|
||||
pub fn with_inputmode(mut self, inputmode: impl Into<Option<Mode>>) -> Self {
|
||||
self.inputmode = inputmode.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,17 +35,21 @@ pub struct Number {
|
|||
/// Devuelve el nombre del campo.
|
||||
name: AttrName,
|
||||
/// Devuelve el valor inicial del campo.
|
||||
value: Attr<u64>,
|
||||
#[getters(copy)]
|
||||
value: Option<u64>,
|
||||
/// Devuelve la etiqueta del campo.
|
||||
label: Lc,
|
||||
/// Devuelve el texto de ayuda del campo.
|
||||
help_text: Lc,
|
||||
/// Devuelve el valor mínimo permitido.
|
||||
min: Attr<u64>,
|
||||
#[getters(copy)]
|
||||
min: Option<u64>,
|
||||
/// Devuelve el valor máximo permitido.
|
||||
max: Attr<u64>,
|
||||
#[getters(copy)]
|
||||
max: Option<u64>,
|
||||
/// Devuelve el incremento entre valores del campo.
|
||||
step: Attr<u64>,
|
||||
#[getters(copy)]
|
||||
step: Option<u64>,
|
||||
/// Devuelve si el campo recibe el foco automáticamente al cargar la página.
|
||||
autofocus: bool,
|
||||
/// Devuelve si el campo es de sólo lectura.
|
||||
|
|
@ -69,7 +73,7 @@ impl Component for Number {
|
|||
fn setup(&mut self, _cx: &Context) {
|
||||
if let Some(container_id) = self
|
||||
.id()
|
||||
.or_else(|| self.name().get().map(|n| util::join!("edit-", n)))
|
||||
.or_else(|| self.name().as_deref().map(|n| util::join!("edit-", n)))
|
||||
{
|
||||
self.alter_prop(PropsOp::ensure_id(container_id));
|
||||
}
|
||||
|
|
@ -100,11 +104,11 @@ impl Component for Number {
|
|||
type="number"
|
||||
id=[input_id.as_deref()]
|
||||
class="form-control"
|
||||
name=[self.name().get()]
|
||||
min=[self.min().get()]
|
||||
max=[self.max().get()]
|
||||
step=[self.step().get()]
|
||||
value=[self.value().get()]
|
||||
name=[self.name().as_deref()]
|
||||
min=[self.min()]
|
||||
max=[self.max()]
|
||||
step=[self.step()]
|
||||
value=[self.value()]
|
||||
autofocus[*self.autofocus()]
|
||||
readonly[*self.readonly()]
|
||||
required[*self.required()]
|
||||
|
|
@ -146,8 +150,8 @@ impl Number {
|
|||
|
||||
/// Establece el valor inicial del campo.
|
||||
#[builder_fn]
|
||||
pub fn with_value(mut self, value: Option<u64>) -> Self {
|
||||
self.value.alter_opt(value);
|
||||
pub fn with_value(mut self, value: impl Into<Option<u64>>) -> Self {
|
||||
self.value = value.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -167,15 +171,15 @@ impl Number {
|
|||
|
||||
/// Establece el valor mínimo permitido (`None` para no imponer mínimo).
|
||||
#[builder_fn]
|
||||
pub fn with_min(mut self, min: Option<u64>) -> Self {
|
||||
self.min.alter_opt(min);
|
||||
pub fn with_min(mut self, min: impl Into<Option<u64>>) -> Self {
|
||||
self.min = min.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece el valor máximo permitido (`None` para no imponer máximo).
|
||||
#[builder_fn]
|
||||
pub fn with_max(mut self, max: Option<u64>) -> Self {
|
||||
self.max.alter_opt(max);
|
||||
pub fn with_max(mut self, max: impl Into<Option<u64>>) -> Self {
|
||||
self.max = max.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -184,8 +188,8 @@ impl Number {
|
|||
/// Pasar `None` omite el atributo `step` y deja que el navegador aplique su valor por defecto
|
||||
/// (normalmente `1`).
|
||||
#[builder_fn]
|
||||
pub fn with_step(mut self, step: Option<u64>) -> Self {
|
||||
self.step.alter_opt(step);
|
||||
pub fn with_step(mut self, step: impl Into<Option<u64>>) -> Self {
|
||||
self.step = step.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ impl Component for Field {
|
|||
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
// En `setup()` se garantiza que `name` e `id` están definidos antes del renderizado.
|
||||
let name = self.name().get().unwrap();
|
||||
let name = self.name().as_deref().unwrap();
|
||||
let container_id = self.id().unwrap();
|
||||
|
||||
Ok(html! {
|
||||
|
|
@ -178,8 +178,8 @@ impl Component for Field {
|
|||
type="radio"
|
||||
id=(&item_id)
|
||||
class="form-check-input"
|
||||
name=(&name)
|
||||
value=[item.value().get()]
|
||||
name=(name)
|
||||
value=[item.value().as_deref()]
|
||||
checked[checked]
|
||||
required[*self.required()]
|
||||
disabled[*item.disabled() || *self.disabled()];
|
||||
|
|
|
|||
|
|
@ -36,17 +36,21 @@ pub struct Range {
|
|||
/// Devuelve el nombre del campo.
|
||||
name: AttrName,
|
||||
/// Devuelve el valor inicial del campo.
|
||||
value: Attr<f64>,
|
||||
#[getters(copy)]
|
||||
value: Option<f64>,
|
||||
/// Devuelve la etiqueta del campo.
|
||||
label: Lc,
|
||||
/// Devuelve el texto de ayuda del campo.
|
||||
help_text: Lc,
|
||||
/// Devuelve el valor mínimo permitido.
|
||||
min: Attr<f64>,
|
||||
#[getters(copy)]
|
||||
min: Option<f64>,
|
||||
/// Devuelve el valor máximo permitido.
|
||||
max: Attr<f64>,
|
||||
#[getters(copy)]
|
||||
max: Option<f64>,
|
||||
/// Devuelve el incremento entre valores del campo.
|
||||
step: Attr<f64>,
|
||||
#[getters(copy)]
|
||||
step: Option<f64>,
|
||||
/// Devuelve si el control recibe el foco automáticamente al cargar la página.
|
||||
autofocus: bool,
|
||||
/// Devuelve si el control está deshabilitado.
|
||||
|
|
@ -66,7 +70,7 @@ impl Component for Range {
|
|||
fn setup(&mut self, _cx: &Context) {
|
||||
if let Some(container_id) = self
|
||||
.id()
|
||||
.or_else(|| self.name().get().map(|n| util::join!("edit-", n)))
|
||||
.or_else(|| self.name().as_deref().map(|n| util::join!("edit-", n)))
|
||||
{
|
||||
self.alter_prop(PropsOp::ensure_id(container_id));
|
||||
};
|
||||
|
|
@ -87,11 +91,11 @@ impl Component for Range {
|
|||
type="range"
|
||||
id=[range_id.as_deref()]
|
||||
class="form-range"
|
||||
name=[self.name().get()]
|
||||
min=[self.min().get()]
|
||||
max=[self.max().get()]
|
||||
step=[self.step().get()]
|
||||
value=[self.value().get()]
|
||||
name=[self.name().as_deref()]
|
||||
min=[self.min()]
|
||||
max=[self.max()]
|
||||
step=[self.step()]
|
||||
value=[self.value()]
|
||||
autofocus[*self.autofocus()]
|
||||
disabled[*self.disabled()];
|
||||
@if let Some(description) = self.help_text().lookup(cx) {
|
||||
|
|
@ -134,8 +138,8 @@ impl Range {
|
|||
/// Pasar `None` omite el atributo `value` y deja que el navegador aplique su valor por defecto
|
||||
/// (normalmente el punto medio del rango).
|
||||
#[builder_fn]
|
||||
pub fn with_value(mut self, value: Option<f64>) -> Self {
|
||||
self.value.alter_opt(value);
|
||||
pub fn with_value(mut self, value: impl Into<Option<f64>>) -> Self {
|
||||
self.value = value.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -157,8 +161,8 @@ impl Range {
|
|||
///
|
||||
/// Pasar `None` omite el atributo `min` y deja que el navegador aplique su valor por defecto.
|
||||
#[builder_fn]
|
||||
pub fn with_min(mut self, min: Option<f64>) -> Self {
|
||||
self.min.alter_opt(min);
|
||||
pub fn with_min(mut self, min: impl Into<Option<f64>>) -> Self {
|
||||
self.min = min.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -166,8 +170,8 @@ impl Range {
|
|||
///
|
||||
/// Pasar `None` omite el atributo `max` y deja que el navegador aplique su valor por defecto.
|
||||
#[builder_fn]
|
||||
pub fn with_max(mut self, max: Option<f64>) -> Self {
|
||||
self.max.alter_opt(max);
|
||||
pub fn with_max(mut self, max: impl Into<Option<f64>>) -> Self {
|
||||
self.max = max.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -176,8 +180,8 @@ impl Range {
|
|||
/// Pasar `None` omite el atributo `step` y deja que el navegador aplique su valor por defecto
|
||||
/// (normalmente `1`).
|
||||
#[builder_fn]
|
||||
pub fn with_step(mut self, step: Option<f64>) -> Self {
|
||||
self.step.alter_opt(step);
|
||||
pub fn with_step(mut self, step: impl Into<Option<f64>>) -> Self {
|
||||
self.step = step.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -205,9 +205,10 @@ pub struct Field {
|
|||
/// Devuelve si la lista permite selección múltiple.
|
||||
multiple: bool,
|
||||
/// Devuelve el número de filas visibles de la lista de selección.
|
||||
rows: Attr<u16>,
|
||||
#[getters(copy)]
|
||||
rows: Option<u16>,
|
||||
/// Devuelve la configuración de autocompletado del campo.
|
||||
autocomplete: Attr<form::Autocomplete>,
|
||||
autocomplete: Option<form::Autocomplete>,
|
||||
/// Devuelve si la lista recibe el foco automáticamente al cargar la página.
|
||||
autofocus: bool,
|
||||
/// Devuelve si la selección de un elemento es obligatoria.
|
||||
|
|
@ -229,7 +230,7 @@ impl Component for Field {
|
|||
fn setup(&mut self, _cx: &Context) {
|
||||
if let Some(container_id) = self
|
||||
.id()
|
||||
.or_else(|| self.name().get().map(|n| util::join!("edit-", n)))
|
||||
.or_else(|| self.name().as_deref().map(|n| util::join!("edit-", n)))
|
||||
{
|
||||
self.alter_prop(PropsOp::ensure_id(container_id));
|
||||
}
|
||||
|
|
@ -260,10 +261,10 @@ impl Component for Field {
|
|||
select
|
||||
id=[select_id.as_deref()]
|
||||
class="form-select"
|
||||
name=[self.name().get()]
|
||||
name=[self.name().as_deref()]
|
||||
multiple[*self.multiple()]
|
||||
size=[self.rows().get()]
|
||||
autocomplete=[self.autocomplete().get()]
|
||||
size=[self.rows()]
|
||||
autocomplete=[self.autocomplete()]
|
||||
autofocus[*self.autofocus()]
|
||||
required[*self.required()]
|
||||
disabled[*self.disabled()]
|
||||
|
|
@ -272,7 +273,7 @@ impl Component for Field {
|
|||
@match entry {
|
||||
Entry::Item(opt) => {
|
||||
option
|
||||
value=(opt.value().as_str().unwrap_or(""))
|
||||
value=(opt.value().as_deref().unwrap_or(""))
|
||||
selected[*opt.selected()]
|
||||
disabled[*opt.disabled()]
|
||||
{
|
||||
|
|
@ -286,7 +287,7 @@ impl Component for Field {
|
|||
{
|
||||
@for opt in group.items() {
|
||||
option
|
||||
value=(opt.value().as_str().unwrap_or(""))
|
||||
value=(opt.value().as_deref().unwrap_or(""))
|
||||
selected[*opt.selected()]
|
||||
disabled[*opt.disabled()]
|
||||
{
|
||||
|
|
@ -389,8 +390,8 @@ impl Field {
|
|||
/// Es especialmente útil con selección múltiple para controlar el número de filas visibles sin
|
||||
/// necesidad de recurrir al desplazamiento.
|
||||
#[builder_fn]
|
||||
pub fn with_rows(mut self, rows: Option<u16>) -> Self {
|
||||
self.rows.alter_opt(rows);
|
||||
pub fn with_rows(mut self, rows: impl Into<Option<u16>>) -> Self {
|
||||
self.rows = rows.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -404,8 +405,11 @@ impl Field {
|
|||
/// Usa los métodos de [`form::Autocomplete`] para los valores más habituales. Pasa `None` para
|
||||
/// omitir el atributo.
|
||||
#[builder_fn]
|
||||
pub fn with_autocomplete(mut self, autocomplete: Option<form::Autocomplete>) -> Self {
|
||||
self.autocomplete.alter_opt(autocomplete);
|
||||
pub fn with_autocomplete(
|
||||
mut self,
|
||||
autocomplete: impl Into<Option<form::Autocomplete>>,
|
||||
) -> Self {
|
||||
self.autocomplete = autocomplete.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,15 +44,18 @@ pub struct Textarea {
|
|||
/// Devuelve el texto de ayuda del campo.
|
||||
help_text: Lc,
|
||||
/// Devuelve el número de filas visibles del área de texto.
|
||||
rows: Attr<u16>,
|
||||
#[getters(copy)]
|
||||
rows: Option<u16>,
|
||||
/// Devuelve la longitud mínima permitida en caracteres.
|
||||
minlength: Attr<u16>,
|
||||
#[getters(copy)]
|
||||
minlength: Option<u16>,
|
||||
/// Devuelve la longitud máxima permitida en caracteres.
|
||||
maxlength: Attr<u16>,
|
||||
#[getters(copy)]
|
||||
maxlength: Option<u16>,
|
||||
/// Devuelve el texto indicativo del área de texto.
|
||||
placeholder: Lc,
|
||||
/// Devuelve la configuración de autocompletado del campo.
|
||||
autocomplete: Attr<form::Autocomplete>,
|
||||
autocomplete: Option<form::Autocomplete>,
|
||||
/// Devuelve si el campo recibe el foco automáticamente al cargar la página.
|
||||
autofocus: bool,
|
||||
/// Devuelve si el campo es de sólo lectura.
|
||||
|
|
@ -76,7 +79,7 @@ impl Component for Textarea {
|
|||
fn setup(&mut self, _cx: &Context) {
|
||||
if let Some(container_id) = self
|
||||
.id()
|
||||
.or_else(|| self.name().get().map(|n| util::join!("edit-", n)))
|
||||
.or_else(|| self.name().as_deref().map(|n| util::join!("edit-", n)))
|
||||
{
|
||||
self.alter_prop(PropsOp::ensure_id(container_id));
|
||||
}
|
||||
|
|
@ -109,18 +112,18 @@ impl Component for Textarea {
|
|||
textarea
|
||||
id=[textarea_id.as_deref()]
|
||||
class="form-control"
|
||||
name=[self.name().get()]
|
||||
rows=[self.rows().get()]
|
||||
minlength=[self.minlength().get()]
|
||||
maxlength=[self.maxlength().get()]
|
||||
name=[self.name().as_deref()]
|
||||
rows=[self.rows()]
|
||||
minlength=[self.minlength()]
|
||||
maxlength=[self.maxlength()]
|
||||
placeholder=[self.placeholder().lookup(cx)]
|
||||
autocomplete=[self.autocomplete().get()]
|
||||
autocomplete=[self.autocomplete()]
|
||||
autofocus[*self.autofocus()]
|
||||
readonly[*self.readonly()]
|
||||
required[*self.required()]
|
||||
disabled[*self.disabled()]
|
||||
{
|
||||
@if let Some(value) = self.value().get() {
|
||||
@if let Some(value) = self.value().as_deref() {
|
||||
(value)
|
||||
}
|
||||
}
|
||||
|
|
@ -185,22 +188,22 @@ impl Textarea {
|
|||
/// Sin valor o pasando `None`, el área muestra su altura predeterminada, dos filas según el
|
||||
/// estándar.
|
||||
#[builder_fn]
|
||||
pub fn with_rows(mut self, rows: Option<u16>) -> Self {
|
||||
self.rows.alter_opt(rows);
|
||||
pub fn with_rows(mut self, rows: impl Into<Option<u16>>) -> Self {
|
||||
self.rows = rows.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece la longitud mínima permitida en caracteres.
|
||||
#[builder_fn]
|
||||
pub fn with_minlength(mut self, minlength: Option<u16>) -> Self {
|
||||
self.minlength.alter_opt(minlength);
|
||||
pub fn with_minlength(mut self, minlength: impl Into<Option<u16>>) -> Self {
|
||||
self.minlength = minlength.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Establece la longitud máxima permitida en caracteres.
|
||||
#[builder_fn]
|
||||
pub fn with_maxlength(mut self, maxlength: Option<u16>) -> Self {
|
||||
self.maxlength.alter_opt(maxlength);
|
||||
pub fn with_maxlength(mut self, maxlength: impl Into<Option<u16>>) -> Self {
|
||||
self.maxlength = maxlength.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -222,8 +225,11 @@ impl Textarea {
|
|||
/// Usa los métodos de [`form::Autocomplete`] para los valores más habituales. Pasa `None` para
|
||||
/// omitir el atributo.
|
||||
#[builder_fn]
|
||||
pub fn with_autocomplete(mut self, autocomplete: Option<form::Autocomplete>) -> Self {
|
||||
self.autocomplete.alter_opt(autocomplete);
|
||||
pub fn with_autocomplete(
|
||||
mut self,
|
||||
autocomplete: impl Into<Option<form::Autocomplete>>,
|
||||
) -> Self {
|
||||
self.autocomplete = autocomplete.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -263,8 +263,8 @@ impl Intro {
|
|||
/// let intro_no_button = Intro::default().with_button(None);
|
||||
/// ```
|
||||
#[builder_fn]
|
||||
pub fn with_button(mut self, button: Option<(Lc, Route)>) -> Self {
|
||||
self.button = button;
|
||||
pub fn with_button(mut self, button: impl Into<Option<(Lc, Route)>>) -> Self {
|
||||
self.button = button.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -203,11 +203,11 @@ impl Component for Pager {
|
|||
return Ok(html! {});
|
||||
}
|
||||
let page = self.current_page().clamp(1, total_pages);
|
||||
let base_path = self.base_path().as_str().unwrap_or_default();
|
||||
let base_path = self.base_path().as_deref().unwrap_or("");
|
||||
|
||||
// Ruta común a los enlaces del paginador, con los parámetros de `extra_query` añadidos a
|
||||
// `base_path`. Pasa por `cx.route()` para preservar el parámetro `lang` si corresponde.
|
||||
let mut route = cx.route(base_path.to_owned());
|
||||
let mut route = cx.route(base_path);
|
||||
for (key, value) in self.extra_query() {
|
||||
route.alter_param(key, value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ impl Column {
|
|||
|
||||
html! {
|
||||
th (self.props()) scope="col" aria-sort=(aria_sort) {
|
||||
a href=[sort.href().as_str()] (link_props) { (label) }
|
||||
a href=[sort.href().as_deref()] (link_props) { (label) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use crate::prelude::*;
|
|||
/// .with_prop(PropsOp::set("data-sort", "email"));
|
||||
///
|
||||
/// assert_eq!(link.props().get_id(), Some("sort-email".to_string()));
|
||||
/// assert_eq!(link.href().as_str(), Some("/admin/users?sort=email"));
|
||||
/// assert_eq!(link.href().as_deref(), Some("/admin/users?sort=email"));
|
||||
/// assert_eq!(link.dir(), Some(&SortDir::Desc));
|
||||
/// ```
|
||||
///
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue