Skip to content

Commit 6327fe6

Browse files
authored
Don't refresh uncontrolled input value (#1374)
1 parent 25b42f2 commit 6327fe6

File tree

1 file changed

+66
-12
lines changed

1 file changed

+66
-12
lines changed

yew/src/virtual_dom/vtag.rs

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ impl VTag {
218218
}
219219

220220
fn refresh_value(&mut self) {
221+
// Don't refresh value if the element is not controlled
222+
if self.value.is_none() {
223+
return;
224+
}
225+
221226
if let Some(element) = self.reference.as_ref() {
222227
if self.element_type == ElementType::Input {
223228
let input_el = cfg_match! {
@@ -1170,7 +1175,7 @@ mod tests {
11701175
}
11711176

11721177
#[test]
1173-
fn check_input_current_value_sync() {
1178+
fn controlled_input_synced() {
11741179
let scope = test_scope();
11751180
let parent = document().create_element("div").unwrap();
11761181

@@ -1182,11 +1187,8 @@ mod tests {
11821187
let expected = "not_changed_value";
11831188

11841189
// Initial state
1185-
let mut elem = html! {
1186-
<input value=expected />
1187-
};
1190+
let mut elem = html! { <input value=expected /> };
11881191
elem.apply(&scope, &parent, NodeRef::default(), None);
1189-
11901192
let vtag = if let VNode::VTag(vtag) = elem {
11911193
vtag
11921194
} else {
@@ -1205,25 +1207,77 @@ mod tests {
12051207
};
12061208

12071209
let ancestor = vtag;
1208-
// Same state after onInput or onChange event
1209-
let elem = html! {
1210-
<input value=expected />
1210+
let mut elem = html! { <input value=expected /> };
1211+
let vtag = assert_vtag(&mut elem);
1212+
1213+
// Sync happens here
1214+
vtag.apply(
1215+
&scope,
1216+
&parent,
1217+
NodeRef::default(),
1218+
Some(VNode::VTag(ancestor)),
1219+
);
1220+
1221+
// Get new current value of the input element
1222+
let input_ref = vtag.reference.as_ref().unwrap();
1223+
let input = cfg_match! {
1224+
feature = "std_web" => InputElement::try_from(input_ref.clone()).ok(),
1225+
feature = "web_sys" => input_ref.dyn_ref::<InputElement>(),
1226+
}
1227+
.unwrap();
1228+
1229+
let current_value = cfg_match! {
1230+
feature = "std_web" => input.raw_value(),
1231+
feature = "web_sys" => input.value(),
12111232
};
1212-
let mut vtag = if let VNode::VTag(vtag) = elem {
1233+
1234+
// check whether not changed virtual dom value has been set to the input element
1235+
assert_eq!(current_value, expected);
1236+
}
1237+
1238+
#[test]
1239+
fn uncontrolled_input_unsynced() {
1240+
let scope = test_scope();
1241+
let parent = document().create_element("div").unwrap();
1242+
1243+
#[cfg(feature = "std_web")]
1244+
document().body().unwrap().append_child(&parent);
1245+
#[cfg(feature = "web_sys")]
1246+
document().body().unwrap().append_child(&parent).unwrap();
1247+
1248+
// Initial state
1249+
let mut elem = html! { <input /> };
1250+
elem.apply(&scope, &parent, NodeRef::default(), None);
1251+
let vtag = if let VNode::VTag(vtag) = elem {
12131252
vtag
12141253
} else {
12151254
panic!("should be vtag")
12161255
};
12171256

1218-
// Sync happens here
1257+
// User input
1258+
let input_ref = vtag.reference.as_ref().unwrap();
1259+
let input = cfg_match! {
1260+
feature = "std_web" => InputElement::try_from(input_ref.clone()).ok(),
1261+
feature = "web_sys" => input_ref.dyn_ref::<InputElement>(),
1262+
};
1263+
cfg_match! {
1264+
feature = "std_web" => input.unwrap().set_raw_value("User input"),
1265+
feature = "web_sys" => input.unwrap().set_value("User input"),
1266+
};
1267+
1268+
let ancestor = vtag;
1269+
let mut elem = html! { <input /> };
1270+
let vtag = assert_vtag(&mut elem);
1271+
1272+
// Value should not be refreshed
12191273
vtag.apply(
12201274
&scope,
12211275
&parent,
12221276
NodeRef::default(),
12231277
Some(VNode::VTag(ancestor)),
12241278
);
12251279

1226-
// Get new current value of the input element
1280+
// Get user value of the input element
12271281
let input_ref = vtag.reference.as_ref().unwrap();
12281282
let input = cfg_match! {
12291283
feature = "std_web" => InputElement::try_from(input_ref.clone()).ok(),
@@ -1237,7 +1291,7 @@ mod tests {
12371291
};
12381292

12391293
// check whether not changed virtual dom value has been set to the input element
1240-
assert_eq!(current_value, expected);
1294+
assert_eq!(current_value, "User input");
12411295
}
12421296

12431297
#[test]

0 commit comments

Comments
 (0)