Fix checked property being reset (#2907)

if the value is uncontrolled, do not touch it. Only if it is explicitly given
This commit is contained in:
WorldSEnder 2022-10-08 17:50:19 +02:00 committed by GitHub
parent 426a1fd81d
commit bb71b5db61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 15 deletions

View File

@ -128,9 +128,9 @@ impl ToTokens for HtmlElement {
.as_ref()
.map(|attr| {
let value = &attr.value;
quote_spanned! {value.span()=> #value}
quote! { ::std::option::Option::Some( #value ) }
})
.unwrap_or(quote! { false });
.unwrap_or(quote! { ::std::option::Option::None });
// other attributes

View File

@ -67,18 +67,22 @@ impl Apply for InputFields {
type Element = InputElement;
fn apply(mut self, root: &BSubtree, el: &Self::Element) -> Self {
// IMPORTANT! This parameter has to be set every time
// IMPORTANT! This parameter has to be set every time it's explicitly given
// to prevent strange behaviour in the browser when the DOM changes
el.set_checked(self.checked);
if let Some(checked) = self.checked {
el.set_checked(checked);
}
self.value = self.value.apply(root, el);
self
}
fn apply_diff(self, root: &BSubtree, el: &Self::Element, bundle: &mut Self) {
// IMPORTANT! This parameter has to be set every time
// IMPORTANT! This parameter has to be set every time it's explicitly given
// to prevent strange behaviour in the browser when the DOM changes
el.set_checked(self.checked);
if let Some(checked) = self.checked {
el.set_checked(checked);
}
self.value.apply_diff(root, el, &mut bundle.value);
}

View File

@ -62,7 +62,7 @@ pub(crate) struct InputFields {
/// It exists to override standard behavior of `checked` attribute, because
/// in original HTML it sets `defaultChecked` value of `InputElement`, but for reactive
/// frameworks it's more useful to control `checked` value of an `InputElement`.
pub(crate) checked: bool,
pub(crate) checked: Option<bool>,
}
impl Deref for InputFields {
@ -81,7 +81,7 @@ impl DerefMut for InputFields {
impl InputFields {
/// Crate new attributes for an [InputElement] element
fn new(value: Option<AttrValue>, checked: bool) -> Self {
fn new(value: Option<AttrValue>, checked: Option<bool>) -> Self {
Self {
value: Value::new(value),
checked,
@ -164,7 +164,7 @@ impl VTag {
#[allow(clippy::too_many_arguments)]
pub fn __new_input(
value: Option<AttrValue>,
checked: bool,
checked: Option<bool>,
node_ref: NodeRef,
key: Option<Key>,
// at bottom for more readable macro-expanded coded
@ -341,20 +341,29 @@ impl VTag {
/// Returns `checked` property of an
/// [InputElement](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input).
/// (Not a value of node's attribute).
pub fn checked(&self) -> bool {
/// (Does not affect the value of the node's attribute).
pub fn checked(&self) -> Option<bool> {
match &self.inner {
VTagInner::Input(f) => f.checked,
_ => false,
_ => None,
}
}
/// Sets `checked` property of an
/// [InputElement](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input).
/// (Not a value of node's attribute).
/// (Does not affect the value of the node's attribute).
pub fn set_checked(&mut self, value: bool) {
if let VTagInner::Input(f) = &mut self.inner {
f.checked = value;
f.checked = Some(value);
}
}
/// Keeps the current value of the `checked` property of an
/// [InputElement](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input).
/// (Does not affect the value of the node's attribute).
pub fn preserve_checked(&mut self) {
if let VTagInner::Input(f) = &mut self.inner {
f.checked = None;
}
}
@ -479,7 +488,9 @@ mod feat_ssr {
write_attr(w, "value", Some(m));
}
if self.checked() {
// Setting is as an attribute sets the `defaultChecked` property. Only emit this
// if it's explicitly set to checked.
if self.checked() == Some(true) {
write_attr(w, "checked", None);
}
}