Remove native and web features from dioxus-html (#3006)
* remove native and web features from dioxus-html * Fix downcasting web events * Fix desktop with tokio disabled
This commit is contained in:
1 parent
677e0e7f4f
commit
cda8bb24f1
54 files changed
+1768
-1512
No files matched your search
@@ -0,0 +1,160 @@
|
||||
use std::{any::Any, collections::HashMap};
|
||||
|
||||
use dioxus_html::{FormValue, HasFileData, HasFormData};
|
||||
use js_sys::Array;
|
||||
use wasm_bindgen::JsValue;
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsCast};
|
||||
use web_sys::{Element, Event};
|
||||
|
||||
use super::WebEventExt;
|
||||
|
||||
pub(crate) struct WebFormData {
|
||||
element: Element,
|
||||
raw: Event,
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::FormData {
|
||||
type WebEvent = Event;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<Self::WebEvent> {
|
||||
self.downcast::<WebFormData>().map(|e| e.raw.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl WebFormData {
|
||||
pub fn new(element: Element, raw: Event) -> Self {
|
||||
Self { element, raw }
|
||||
}
|
||||
}
|
||||
|
||||
impl HasFormData for WebFormData {
|
||||
fn value(&self) -> String {
|
||||
let target = &self.element;
|
||||
target
|
||||
.dyn_ref()
|
||||
.map(|input: &web_sys::HtmlInputElement| {
|
||||
// todo: special case more input types
|
||||
match input.type_().as_str() {
|
||||
"checkbox" => {
|
||||
match input.checked() {
|
||||
true => "true".to_string(),
|
||||
false => "false".to_string(),
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
input.value()
|
||||
}
|
||||
}
|
||||
})
|
||||
.or_else(|| {
|
||||
target
|
||||
.dyn_ref()
|
||||
.map(|input: &web_sys::HtmlTextAreaElement| input.value())
|
||||
})
|
||||
// select elements are NOT input events - because - why woudn't they be??
|
||||
.or_else(|| {
|
||||
target
|
||||
.dyn_ref()
|
||||
.map(|input: &web_sys::HtmlSelectElement| input.value())
|
||||
})
|
||||
.or_else(|| {
|
||||
target
|
||||
.dyn_ref::<web_sys::HtmlElement>()
|
||||
.unwrap()
|
||||
.text_content()
|
||||
})
|
||||
.expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener")
|
||||
}
|
||||
|
||||
fn values(&self) -> HashMap<String, FormValue> {
|
||||
let mut values = HashMap::new();
|
||||
|
||||
fn insert_value(map: &mut HashMap<String, FormValue>, key: String, new_value: String) {
|
||||
map.entry(key.clone()).or_default().0.push(new_value);
|
||||
}
|
||||
|
||||
// try to fill in form values
|
||||
if let Some(form) = self.element.dyn_ref::<web_sys::HtmlFormElement>() {
|
||||
let form_data = get_form_data(form);
|
||||
for value in form_data.entries().into_iter().flatten() {
|
||||
if let Ok(array) = value.dyn_into::<Array>() {
|
||||
if let Some(name) = array.get(0).as_string() {
|
||||
if let Ok(item_values) = array.get(1).dyn_into::<Array>() {
|
||||
item_values
|
||||
.iter()
|
||||
.filter_map(|v| v.as_string())
|
||||
.for_each(|v| insert_value(&mut values, name.clone(), v));
|
||||
} else if let Ok(item_value) = array.get(1).dyn_into::<JsValue>() {
|
||||
insert_value(&mut values, name, item_value.as_string().unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(select) = self.element.dyn_ref::<web_sys::HtmlSelectElement>() {
|
||||
// try to fill in select element values
|
||||
let options = get_select_data(select);
|
||||
values.insert("options".to_string(), FormValue(options));
|
||||
}
|
||||
|
||||
values
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
&self.raw as &dyn Any
|
||||
}
|
||||
}
|
||||
|
||||
impl HasFileData for WebFormData {
|
||||
#[cfg(feature = "file_engine")]
|
||||
fn files(&self) -> Option<std::sync::Arc<dyn dioxus_html::FileEngine>> {
|
||||
let files = self
|
||||
.element
|
||||
.dyn_ref()
|
||||
.and_then(|input: &web_sys::HtmlInputElement| {
|
||||
input.files().and_then(|files| {
|
||||
#[allow(clippy::arc_with_non_send_sync)]
|
||||
crate::file_engine::WebFileEngine::new(files).map(|f| {
|
||||
std::sync::Arc::new(f) as std::sync::Arc<dyn dioxus_html::FileEngine>
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
files
|
||||
}
|
||||
}
|
||||
|
||||
// web-sys does not expose the keys api for select data, so we need to manually bind to it
|
||||
#[wasm_bindgen(inline_js = r#"
|
||||
export function get_select_data(select) {
|
||||
let values = [];
|
||||
for (let i = 0; i < select.options.length; i++) {
|
||||
let option = select.options[i];
|
||||
if (option.selected) {
|
||||
values.push(option.value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
"#)]
|
||||
extern "C" {
|
||||
fn get_select_data(select: &web_sys::HtmlSelectElement) -> Vec<String>;
|
||||
}
|
||||
|
||||
// web-sys does not expose the keys api for form data, so we need to manually bind to it
|
||||
#[wasm_bindgen(inline_js = r#"
|
||||
export function get_form_data(form) {
|
||||
let values = new Map();
|
||||
const formData = new FormData(form);
|
||||
|
||||
for (let name of formData.keys()) {
|
||||
values.set(name, formData.getAll(name));
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
"#)]
|
||||
extern "C" {
|
||||
fn get_form_data(form: &web_sys::HtmlFormElement) -> js_sys::Map;
|
||||
}
|
||||
Reference in new issue
Block a user