♻️ (bootsier): Mueve input/select/textarea a theme
Consolida los handlers de estos campos en la capa del tema. Además, `with_floating_label()` usa un valor extra que lee en `setup()` para forzar `multiple`/`rows` en 'select` y `textarea`.
This commit is contained in:
parent
bff7cf1b38
commit
87ad78778d
7 changed files with 241 additions and 223 deletions
|
|
@ -1,59 +0,0 @@
|
||||||
use pagetop::prelude::*;
|
|
||||||
|
|
||||||
pub fn render(c: &form::input::Field, cx: &mut Context) -> Result<Markup, ComponentError> {
|
|
||||||
let container_id = c.id();
|
|
||||||
let input_id = container_id.as_deref().map(|id| util::join!(id, "-input"));
|
|
||||||
let floating = c.props().has_class("form-floating");
|
|
||||||
let input_class = if *c.plaintext() {
|
|
||||||
"form-control-plaintext"
|
|
||||||
} else {
|
|
||||||
"form-control"
|
|
||||||
};
|
|
||||||
// La etiqueta flotante requiere `placeholder` para animar la etiqueta; si no está definido, se
|
|
||||||
// fuerza `placeholder=""`.
|
|
||||||
let placeholder = if floating {
|
|
||||||
Some(c.placeholder().lookup(cx).unwrap_or_default())
|
|
||||||
} else {
|
|
||||||
c.placeholder().lookup(cx)
|
|
||||||
};
|
|
||||||
let label = match c.label().lookup(cx) {
|
|
||||||
Some(text) => html! {
|
|
||||||
label for=[input_id.as_deref()] class="form-label" {
|
|
||||||
(text)
|
|
||||||
@if *c.required() {
|
|
||||||
span
|
|
||||||
class="form-required"
|
|
||||||
title=(L10n::l("field_required").using(cx))
|
|
||||||
{
|
|
||||||
"*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => html! {},
|
|
||||||
};
|
|
||||||
Ok(html! {
|
|
||||||
div (c.props()) {
|
|
||||||
@if !floating { (label) }
|
|
||||||
input
|
|
||||||
type=(c.kind())
|
|
||||||
id=[input_id.as_deref()]
|
|
||||||
class=(input_class)
|
|
||||||
name=[c.name().get()]
|
|
||||||
value=[c.value().get()]
|
|
||||||
minlength=[c.minlength().get()]
|
|
||||||
maxlength=[c.maxlength().get()]
|
|
||||||
placeholder=[placeholder]
|
|
||||||
inputmode=[c.inputmode().get()]
|
|
||||||
autocomplete=[c.autocomplete().get()]
|
|
||||||
autofocus[*c.autofocus()]
|
|
||||||
readonly[*c.readonly() || *c.plaintext()]
|
|
||||||
required[*c.required()]
|
|
||||||
disabled[*c.disabled()];
|
|
||||||
@if floating { (label) }
|
|
||||||
@if let Some(description) = c.help_text().lookup(cx) {
|
|
||||||
div class="form-text" { (description) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
use pagetop::prelude::*;
|
|
||||||
|
|
||||||
pub fn setup(c: &mut form::select::Field) {
|
|
||||||
if c.props().has_class("form-floating") {
|
|
||||||
c.alter_multiple(false);
|
|
||||||
c.alter_rows(None::<u16>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render(c: &form::select::Field, cx: &mut Context) -> Result<Markup, ComponentError> {
|
|
||||||
let container_id = c.id();
|
|
||||||
let select_id = container_id.as_deref().map(|id| util::join!(id, "-select"));
|
|
||||||
let floating = c.props().has_class("form-floating");
|
|
||||||
let label = match c.label().lookup(cx) {
|
|
||||||
Some(text) => html! {
|
|
||||||
label for=[select_id.as_deref()] class="form-label" {
|
|
||||||
(text)
|
|
||||||
@if *c.required() {
|
|
||||||
span
|
|
||||||
class="form-required"
|
|
||||||
title=(L10n::l("field_required").using(cx))
|
|
||||||
{
|
|
||||||
"*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => html! {},
|
|
||||||
};
|
|
||||||
Ok(html! {
|
|
||||||
div (c.props()) {
|
|
||||||
@if !floating { (label) }
|
|
||||||
select
|
|
||||||
id=[select_id.as_deref()]
|
|
||||||
class="form-select"
|
|
||||||
name=[c.name().get()]
|
|
||||||
multiple[*c.multiple()]
|
|
||||||
size=[c.rows().get()]
|
|
||||||
autocomplete=[c.autocomplete().get()]
|
|
||||||
autofocus[*c.autofocus()]
|
|
||||||
required[*c.required()]
|
|
||||||
disabled[*c.disabled()]
|
|
||||||
{
|
|
||||||
@for entry in c.entries() {
|
|
||||||
@match entry {
|
|
||||||
form::select::Entry::Item(opt) => {
|
|
||||||
option
|
|
||||||
value=(opt.value().as_str().unwrap_or(""))
|
|
||||||
selected[*opt.selected()]
|
|
||||||
disabled[*opt.disabled()]
|
|
||||||
{
|
|
||||||
(opt.label().using(cx))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
form::select::Entry::Group(group) => {
|
|
||||||
optgroup
|
|
||||||
label=(group.label().using(cx))
|
|
||||||
disabled[*group.disabled()]
|
|
||||||
{
|
|
||||||
@for opt in group.items() {
|
|
||||||
option
|
|
||||||
value=(opt.value().as_str().unwrap_or(""))
|
|
||||||
selected[*opt.selected()]
|
|
||||||
disabled[*opt.disabled()]
|
|
||||||
{
|
|
||||||
(opt.label().using(cx))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@if floating { (label) }
|
|
||||||
@if let Some(description) = c.help_text().lookup(cx) {
|
|
||||||
div class="form-text" { (description) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
use pagetop::prelude::*;
|
|
||||||
|
|
||||||
pub fn setup(c: &mut form::Textarea) {
|
|
||||||
if c.props().has_class("form-floating") {
|
|
||||||
c.alter_rows(None::<u16>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render(c: &form::Textarea, cx: &mut Context) -> Result<Markup, ComponentError> {
|
|
||||||
let container_id = c.id();
|
|
||||||
let textarea_id = container_id
|
|
||||||
.as_deref()
|
|
||||||
.map(|id| util::join!(id, "-textarea"));
|
|
||||||
let floating = c.props().has_class("form-floating");
|
|
||||||
// La etiqueta flotante requiere `placeholder` para animar la etiqueta; si no está definido se
|
|
||||||
// fuerza `placeholder=""`.
|
|
||||||
let placeholder = if floating {
|
|
||||||
Some(c.placeholder().lookup(cx).unwrap_or_default())
|
|
||||||
} else {
|
|
||||||
c.placeholder().lookup(cx)
|
|
||||||
};
|
|
||||||
let label = match c.label().lookup(cx) {
|
|
||||||
Some(text) => html! {
|
|
||||||
label for=[textarea_id.as_deref()] class="form-label" {
|
|
||||||
(text)
|
|
||||||
@if *c.required() {
|
|
||||||
span
|
|
||||||
class="form-required"
|
|
||||||
title=(L10n::l("field_required").using(cx))
|
|
||||||
{
|
|
||||||
"*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => html! {},
|
|
||||||
};
|
|
||||||
Ok(html! {
|
|
||||||
div (c.props()) {
|
|
||||||
@if !floating { (label) }
|
|
||||||
textarea
|
|
||||||
id=[textarea_id.as_deref()]
|
|
||||||
class="form-control"
|
|
||||||
name=[c.name().get()]
|
|
||||||
rows=[c.rows().get()]
|
|
||||||
minlength=[c.minlength().get()]
|
|
||||||
maxlength=[c.maxlength().get()]
|
|
||||||
placeholder=[placeholder]
|
|
||||||
autocomplete=[c.autocomplete().get()]
|
|
||||||
autofocus[*c.autofocus()]
|
|
||||||
readonly[*c.readonly()]
|
|
||||||
required[*c.required()]
|
|
||||||
disabled[*c.disabled()]
|
|
||||||
{
|
|
||||||
@if let Some(value) = c.value().get() { (value) }
|
|
||||||
}
|
|
||||||
@if floating { (label) }
|
|
||||||
@if let Some(description) = c.help_text().lookup(cx) {
|
|
||||||
div class="form-text" { (description) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -143,14 +143,15 @@ impl Theme for Bootsier {
|
||||||
cx: &mut Context,
|
cx: &mut Context,
|
||||||
) -> Option<Result<Markup, ComponentError>> {
|
) -> Option<Result<Markup, ComponentError>> {
|
||||||
setup_component!(component, {
|
setup_component!(component, {
|
||||||
Button => |c| handlers::button::setup(c),
|
Button => |c| theme::bs::button::setup(c),
|
||||||
form::select::Field => |c| handlers::select::setup(c),
|
form::input::Field => |c| theme::bs::form::input::setup(c),
|
||||||
form::Textarea => |c| handlers::textarea::setup(c),
|
form::select::Field => |c| theme::bs::form::select::setup(c),
|
||||||
|
form::Textarea => |c| theme::bs::form::textarea::setup(c),
|
||||||
});
|
});
|
||||||
render_component!(component, {
|
render_component!(component, {
|
||||||
form::input::Field => |c| handlers::input::render(c, cx),
|
form::input::Field => |c| theme::bs::form::input::render(c, cx),
|
||||||
form::select::Field => |c| handlers::select::render(c, cx),
|
form::select::Field => |c| theme::bs::form::select::render(c, cx),
|
||||||
form::Textarea => |c| handlers::textarea::render(c, cx),
|
form::Textarea => |c| theme::bs::form::textarea::render(c, cx),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ use pagetop::prelude::*;
|
||||||
|
|
||||||
pub use pagetop::base::component::form::input::{Field, Kind, Mode};
|
pub use pagetop::base::component::form::input::{Field, Kind, Mode};
|
||||||
|
|
||||||
|
const EXTRA_FLOATING_LABEL: &str = "bootsier.form.input.floating_label";
|
||||||
|
|
||||||
/// Extensión de Bootsier para [`form::input::Field`].
|
/// Extensión de Bootsier para [`form::input::Field`].
|
||||||
///
|
///
|
||||||
/// Proporciona soporte para **etiquetas flotantes** (*floating label*). La etiqueta flotante se
|
/// Proporciona soporte para **etiquetas flotantes** (*floating label*). La etiqueta flotante se
|
||||||
|
|
@ -31,10 +33,76 @@ pub trait InputBootsier {
|
||||||
|
|
||||||
impl InputBootsier for Field {
|
impl InputBootsier for Field {
|
||||||
fn with_floating_label(self, floating: bool) -> Self {
|
fn with_floating_label(self, floating: bool) -> Self {
|
||||||
if floating {
|
self.with_prop(PropsOp::set_extra(EXTRA_FLOATING_LABEL, floating))
|
||||||
self.with_prop(PropsOp::add_classes("form-floating"))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Field SETUP >********************************************************************************
|
||||||
|
|
||||||
|
pub(crate) fn setup(field: &mut Field) {
|
||||||
|
if field.props().extra_or(EXTRA_FLOATING_LABEL, false) {
|
||||||
|
field.alter_prop(PropsOp::add_classes("form-floating"));
|
||||||
} else {
|
} else {
|
||||||
self.with_prop(PropsOp::remove_classes("form-floating"))
|
field.alter_prop(PropsOp::remove_classes("form-floating"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Field RENDER >*******************************************************************************
|
||||||
|
|
||||||
|
pub(crate) fn render(field: &Field, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
|
let container_id = field.id();
|
||||||
|
let input_id = container_id.as_deref().map(|id| util::join!(id, "-input"));
|
||||||
|
let floating = field.props().extra_or(EXTRA_FLOATING_LABEL, false);
|
||||||
|
let input_class = if *field.plaintext() {
|
||||||
|
"form-control-plaintext"
|
||||||
|
} else {
|
||||||
|
"form-control"
|
||||||
|
};
|
||||||
|
// La etiqueta flotante requiere `placeholder` para animar la etiqueta; si no está definido, se
|
||||||
|
// fuerza `placeholder=""`.
|
||||||
|
let placeholder = if floating {
|
||||||
|
Some(field.placeholder().lookup(cx).unwrap_or_default())
|
||||||
|
} else {
|
||||||
|
field.placeholder().lookup(cx)
|
||||||
|
};
|
||||||
|
let label = match field.label().lookup(cx) {
|
||||||
|
Some(text) => html! {
|
||||||
|
label for=[input_id.as_deref()] class="form-label" {
|
||||||
|
(text)
|
||||||
|
@if *field.required() {
|
||||||
|
span
|
||||||
|
class="form-required"
|
||||||
|
title=(L10n::l("field_required").using(cx))
|
||||||
|
{
|
||||||
|
"*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
None => html! {},
|
||||||
|
};
|
||||||
|
Ok(html! {
|
||||||
|
div (field.props()) {
|
||||||
|
@if !floating { (label) }
|
||||||
|
input
|
||||||
|
type=(field.kind())
|
||||||
|
id=[input_id.as_deref()]
|
||||||
|
class=(input_class)
|
||||||
|
name=[field.name().get()]
|
||||||
|
value=[field.value().get()]
|
||||||
|
minlength=[field.minlength().get()]
|
||||||
|
maxlength=[field.maxlength().get()]
|
||||||
|
placeholder=[placeholder]
|
||||||
|
inputmode=[field.inputmode().get()]
|
||||||
|
autocomplete=[field.autocomplete().get()]
|
||||||
|
autofocus[*field.autofocus()]
|
||||||
|
readonly[*field.readonly() || *field.plaintext()]
|
||||||
|
required[*field.required()]
|
||||||
|
disabled[*field.disabled()];
|
||||||
|
@if floating { (label) }
|
||||||
|
@if let Some(description) = field.help_text().lookup(cx) {
|
||||||
|
div class="form-text" { (description) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ use pagetop::prelude::*;
|
||||||
|
|
||||||
pub use pagetop::base::component::form::select::{Entry, Field, Group, Item};
|
pub use pagetop::base::component::form::select::{Entry, Field, Group, Item};
|
||||||
|
|
||||||
|
const EXTRA_FLOATING_LABEL: &str = "bootsier.form.select.floating_label";
|
||||||
|
|
||||||
/// Extensión de Bootsier para [`form::select::Field`].
|
/// Extensión de Bootsier para [`form::select::Field`].
|
||||||
///
|
///
|
||||||
/// Proporciona soporte para **etiquetas flotantes** (*floating label*). La etiqueta flotante se
|
/// Proporciona soporte para **etiquetas flotantes** (*floating label*). La etiqueta flotante se
|
||||||
|
|
@ -36,10 +38,92 @@ pub trait SelectBootsier {
|
||||||
|
|
||||||
impl SelectBootsier for Field {
|
impl SelectBootsier for Field {
|
||||||
fn with_floating_label(self, floating: bool) -> Self {
|
fn with_floating_label(self, floating: bool) -> Self {
|
||||||
if floating {
|
self.with_prop(PropsOp::set_extra(EXTRA_FLOATING_LABEL, floating))
|
||||||
self.with_prop(PropsOp::add_classes("form-floating"))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Field SETUP >********************************************************************************
|
||||||
|
|
||||||
|
pub(crate) fn setup(field: &mut Field) {
|
||||||
|
if field.props().extra_or(EXTRA_FLOATING_LABEL, false) {
|
||||||
|
field.alter_prop(PropsOp::add_classes("form-floating"));
|
||||||
|
field.alter_multiple(false);
|
||||||
|
field.alter_rows(None::<u16>);
|
||||||
} else {
|
} else {
|
||||||
self.with_prop(PropsOp::remove_classes("form-floating"))
|
field.alter_prop(PropsOp::remove_classes("form-floating"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Field RENDER >*******************************************************************************
|
||||||
|
|
||||||
|
pub(crate) fn render(field: &Field, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
|
let container_id = field.id();
|
||||||
|
let select_id = container_id.as_deref().map(|id| util::join!(id, "-select"));
|
||||||
|
let floating = field.props().extra_or(EXTRA_FLOATING_LABEL, false);
|
||||||
|
let label = match field.label().lookup(cx) {
|
||||||
|
Some(text) => html! {
|
||||||
|
label for=[select_id.as_deref()] class="form-label" {
|
||||||
|
(text)
|
||||||
|
@if *field.required() {
|
||||||
|
span
|
||||||
|
class="form-required"
|
||||||
|
title=(L10n::l("field_required").using(cx))
|
||||||
|
{
|
||||||
|
"*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
None => html! {},
|
||||||
|
};
|
||||||
|
Ok(html! {
|
||||||
|
div (field.props()) {
|
||||||
|
@if !floating { (label) }
|
||||||
|
select
|
||||||
|
id=[select_id.as_deref()]
|
||||||
|
class="form-select"
|
||||||
|
name=[field.name().get()]
|
||||||
|
multiple[*field.multiple()]
|
||||||
|
size=[field.rows().get()]
|
||||||
|
autocomplete=[field.autocomplete().get()]
|
||||||
|
autofocus[*field.autofocus()]
|
||||||
|
required[*field.required()]
|
||||||
|
disabled[*field.disabled()]
|
||||||
|
{
|
||||||
|
@for entry in field.entries() {
|
||||||
|
@match entry {
|
||||||
|
form::select::Entry::Item(opt) => {
|
||||||
|
option
|
||||||
|
value=(opt.value().as_str().unwrap_or(""))
|
||||||
|
selected[*opt.selected()]
|
||||||
|
disabled[*opt.disabled()]
|
||||||
|
{
|
||||||
|
(opt.label().using(cx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
form::select::Entry::Group(group) => {
|
||||||
|
optgroup
|
||||||
|
label=(group.label().using(cx))
|
||||||
|
disabled[*group.disabled()]
|
||||||
|
{
|
||||||
|
@for opt in group.items() {
|
||||||
|
option
|
||||||
|
value=(opt.value().as_str().unwrap_or(""))
|
||||||
|
selected[*opt.selected()]
|
||||||
|
disabled[*opt.disabled()]
|
||||||
|
{
|
||||||
|
(opt.label().using(cx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@if floating { (label) }
|
||||||
|
@if let Some(description) = field.help_text().lookup(cx) {
|
||||||
|
div class="form-text" { (description) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ use pagetop::prelude::*;
|
||||||
|
|
||||||
pub use pagetop::base::component::form::Textarea;
|
pub use pagetop::base::component::form::Textarea;
|
||||||
|
|
||||||
|
const EXTRA_FLOATING_LABEL: &str = "bootsier.form.textarea.floating_label";
|
||||||
|
|
||||||
/// Extensión de Bootsier para [`form::Textarea`].
|
/// Extensión de Bootsier para [`form::Textarea`].
|
||||||
///
|
///
|
||||||
/// Proporciona soporte para **etiquetas flotantes** (*floating label*). La etiqueta flotante se
|
/// Proporciona soporte para **etiquetas flotantes** (*floating label*). La etiqueta flotante se
|
||||||
|
|
@ -34,10 +36,75 @@ pub trait TextareaBootsier {
|
||||||
|
|
||||||
impl TextareaBootsier for Textarea {
|
impl TextareaBootsier for Textarea {
|
||||||
fn with_floating_label(self, floating: bool) -> Self {
|
fn with_floating_label(self, floating: bool) -> Self {
|
||||||
if floating {
|
self.with_prop(PropsOp::set_extra(EXTRA_FLOATING_LABEL, floating))
|
||||||
self.with_prop(PropsOp::add_classes("form-floating"))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Textarea SETUP >*****************************************************************************
|
||||||
|
|
||||||
|
pub(crate) fn setup(field: &mut Textarea) {
|
||||||
|
if field.props().extra_or(EXTRA_FLOATING_LABEL, false) {
|
||||||
|
field.alter_prop(PropsOp::add_classes("form-floating"));
|
||||||
|
field.alter_rows(None::<u16>);
|
||||||
} else {
|
} else {
|
||||||
self.with_prop(PropsOp::remove_classes("form-floating"))
|
field.alter_prop(PropsOp::remove_classes("form-floating"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Textarea RENDER >****************************************************************************
|
||||||
|
|
||||||
|
pub(crate) fn render(field: &Textarea, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
|
let container_id = field.id();
|
||||||
|
let textarea_id = container_id
|
||||||
|
.as_deref()
|
||||||
|
.map(|id| util::join!(id, "-textarea"));
|
||||||
|
let floating = field.props().extra_or(EXTRA_FLOATING_LABEL, false);
|
||||||
|
// La etiqueta flotante requiere `placeholder` para animar la etiqueta; si no está definido se
|
||||||
|
// fuerza `placeholder=""`.
|
||||||
|
let placeholder = if floating {
|
||||||
|
Some(field.placeholder().lookup(cx).unwrap_or_default())
|
||||||
|
} else {
|
||||||
|
field.placeholder().lookup(cx)
|
||||||
|
};
|
||||||
|
let label = match field.label().lookup(cx) {
|
||||||
|
Some(text) => html! {
|
||||||
|
label for=[textarea_id.as_deref()] class="form-label" {
|
||||||
|
(text)
|
||||||
|
@if *field.required() {
|
||||||
|
span
|
||||||
|
class="form-required"
|
||||||
|
title=(L10n::l("field_required").using(cx))
|
||||||
|
{
|
||||||
|
"*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
None => html! {},
|
||||||
|
};
|
||||||
|
Ok(html! {
|
||||||
|
div (field.props()) {
|
||||||
|
@if !floating { (label) }
|
||||||
|
textarea
|
||||||
|
id=[textarea_id.as_deref()]
|
||||||
|
class="form-control"
|
||||||
|
name=[field.name().get()]
|
||||||
|
rows=[field.rows().get()]
|
||||||
|
minlength=[field.minlength().get()]
|
||||||
|
maxlength=[field.maxlength().get()]
|
||||||
|
placeholder=[placeholder]
|
||||||
|
autocomplete=[field.autocomplete().get()]
|
||||||
|
autofocus[*field.autofocus()]
|
||||||
|
readonly[*field.readonly()]
|
||||||
|
required[*field.required()]
|
||||||
|
disabled[*field.disabled()]
|
||||||
|
{
|
||||||
|
@if let Some(value) = field.value().get() { (value) }
|
||||||
|
}
|
||||||
|
@if floating { (label) }
|
||||||
|
@if let Some(description) = field.help_text().lookup(cx) {
|
||||||
|
div class="form-text" { (description) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue