|
1 | 1 | use std::fmt::Display; |
2 | | -use web_sys::{Event, FileList, HtmlInputElement, InputEvent, MouseEvent}; |
| 2 | +use web_sys::{Event, FileList, HtmlInputElement, InputEvent, InputEventInit, MouseEvent}; |
3 | 3 | use yew::{ |
4 | 4 | classes, function_component, html, use_force_update, use_node_ref, use_state, |
5 | 5 | virtual_dom::{VChild, VNode}, |
@@ -93,12 +93,15 @@ where |
93 | 93 | trigger.force_update(); |
94 | 94 | } |
95 | 95 |
|
96 | | - if let (false, Some(default), Some(input_element)) = ( |
97 | | - *applied_default_value, |
98 | | - props.default.as_ref(), |
99 | | - node_ref.cast::<HtmlInputElement>(), |
100 | | - ) { |
101 | | - input_element.set_value(&default.to_string()); |
| 96 | + if let (false, Some(input_element)) = |
| 97 | + (*applied_default_value, node_ref.cast::<HtmlInputElement>()) |
| 98 | + { |
| 99 | + if let Some(d) = props.default.as_ref() { |
| 100 | + input_element.set_value(&d.to_string()); |
| 101 | + input_element |
| 102 | + .dispatch_event(&InputEvent::new("input").unwrap()) |
| 103 | + .unwrap(); |
| 104 | + } |
102 | 105 | applied_default_value.set(true); |
103 | 106 | } |
104 | 107 |
|
@@ -346,30 +349,46 @@ where |
346 | 349 | // so the noderef becomes valid. |
347 | 350 | let first_render = use_state(|| true); |
348 | 351 | let trigger = use_force_update(); |
349 | | - let applied_default_value = use_state(|| false); |
350 | 352 | let node_ref = use_node_ref(); |
351 | 353 |
|
352 | 354 | if *first_render { |
353 | 355 | first_render.set(false); |
354 | 356 | trigger.force_update(); |
355 | 357 | } |
356 | 358 |
|
357 | | - if let (false, Some(default), Some(input_element)) = ( |
358 | | - *applied_default_value, |
359 | | - props.default.as_ref(), |
360 | | - node_ref.cast::<HtmlInputElement>(), |
361 | | - ) { |
362 | | - input_element.set_value(default.as_ref()); |
363 | | - applied_default_value.set(true); |
| 359 | + let user_edited = use_state(|| false); |
| 360 | + let last_default_value = use_state(|| None); |
| 361 | + if let Some(input_element) = node_ref.cast::<HtmlInputElement>() { |
| 362 | + if !*user_edited && props.default != *last_default_value { |
| 363 | + if let Some(d) = props.default.as_ref() { |
| 364 | + input_element.set_value(d); |
| 365 | + } else { |
| 366 | + input_element.set_value(""); |
| 367 | + } |
| 368 | + let mut init = InputEventInit::new(); |
| 369 | + init.data(Some("ignore")); |
| 370 | + input_element |
| 371 | + .dispatch_event(&InputEvent::new_with_event_init_dict("input", &init).unwrap()) |
| 372 | + .unwrap(); |
| 373 | + last_default_value.set(props.default.clone()); |
| 374 | + } |
364 | 375 | } |
365 | 376 |
|
| 377 | + let prop_oninput = props.oninput.clone(); |
| 378 | + let oninput = Callback::from(move |event: InputEvent| { |
| 379 | + if !event.data().map_or(false, |d| d == "ignore") { |
| 380 | + prop_oninput.emit(event); |
| 381 | + user_edited.set(true); |
| 382 | + } |
| 383 | + }); |
| 384 | + |
366 | 385 | html! { |
367 | 386 | <> |
368 | 387 | <label class="form-label" for={id.clone()}> |
369 | 388 | { props.label } |
370 | 389 | </label> |
371 | 390 | <div class={classes!(if success || error { Some("has-icon-right") } else { None })}> |
372 | | - <textarea class="form-input" id={id} oninput={props.oninput.clone()} |
| 391 | + <textarea class="form-input" id={id} oninput={oninput} |
373 | 392 | ref={node_ref} |
374 | 393 | placeholder={props.placeholder.as_ref().cloned()} |
375 | 394 | rows={props.rows.as_ref().map(ToString::to_string)} |
|
0 commit comments