Skip to content

Commit

Permalink
Merge pull request #102 from MassiminoilTrace/master
Browse files Browse the repository at this point in the history
File engine documentation
  • Loading branch information
ealmloff authored Aug 28, 2023
2 parents fdf412b + dfdcd9d commit 1119f27
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 0 deletions.
25 changes: 25 additions & 0 deletions docs-src/0.4/en/reference/user_input.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,28 @@ DemoFrame {
```
Submitted! UiEvent { data: FormData { value: "", values: {"age": "very old", "date": "1966", "name": "Fred"} } }
```

## Handling files
You can insert a file picker by using an input element of type `file`. This element supports the `multiple` attribute, to let you pick more files at the same time. You can select a folder by adding the `directory` attribute: Dioxus will map this attribute to browser specific attributes, because there is no standardized way to allow a directory to be selected.

`type` is a Rust keyword, so when specifying the type of the input field, you have to write it as `r#type:"file"`.

Extracting the selected files is a bit different from what you may typically use in Javascript.

The `FormData` event contains a `files` field with data about the uploaded files. This field contains a `FileEngine` struct which lets you fetch the filenames selected by the user. This example saves the filenames of the selected files to a `Vec`:

```rust, no_run
{{#include src/doc_examples/input_fileengine.rs:component}}
```

If you're planning to read the file content, you need to do it asynchronously, to keep the rest of the UI interactive. This example event handler loads the content of the selected files in an async closure:

```rust, no_run
{{#include src/doc_examples/input_fileengine_async.rs:onchange_event}}
```

Lastly, this example shows you how to select a folder, by setting the `directory` attribute to `true`.

```rust, no_run
{{#include src/doc_examples/input_fileengine_folder.rs:rsx}}
```
28 changes: 28 additions & 0 deletions src/doc_examples/input_fileengine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#![allow(non_snake_case)]
use dioxus::prelude::*;

// ANCHOR: component
pub fn App(cx: Scope) -> Element {
// ANCHOR: rsx
let filenames: &UseRef<Vec<String>> = use_ref(cx, Vec::new);
cx.render(rsx! {
input {
// tell the input to pick a file
r#type:"file",
// list the accepted extensions
accept: ".txt, .rs",
// pick multiple files
multiple: true,
onchange: |evt| {
if let Some(file_engine) = &evt.files {
let files = file_engine.files();
for file_name in &files {
filenames.write().push(file_name);
}
}
}
}
})
// ANCHOR_END: rsx
}
// ANCHOR_END: component
34 changes: 34 additions & 0 deletions src/doc_examples/input_fileengine_async.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#![allow(non_snake_case)]
use dioxus::prelude::*;

// ANCHOR: component
pub fn App(cx: Scope) -> Element {
let files_uploaded: &UseRef<Vec<String>> = use_ref(cx, Vec::new);

cx.render(rsx! {
input {
r#type:"file",
accept: ".txt, .rs",
multiple: true,
// ANCHOR: onchange_event
onchange: |evt| {
// A helper macro to use hooks in async environments
to_owned![files_uploaded];
async move {
if let Some(file_engine) = &evt.files {
let files = file_engine.files();
for file_name in &files {
// Make sure to use async/await when doing heavy I/O operations,
// to not freeze the interface in the meantime
if let Some(file) = file_engine.read_file_to_string(file_name).await{
files_uploaded.write().push(file);
}
}
}
}
}
// ANCHOR_END: onchange_event
}
})
}
// ANCHOR_END: component
26 changes: 26 additions & 0 deletions src/doc_examples/input_fileengine_folder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#![allow(non_snake_case)]
use dioxus::prelude::*;

// ANCHOR: component
pub fn App(cx: Scope) -> Element {
let filenames: &UseRef<Vec<String>> = use_ref(cx, Vec::new);
cx.render(rsx! {
// ANCHOR: rsx
input {
r#type:"file",
// Select a folder by setting the directory attribute
directory: true,
onchange: |evt| {
if let Some(file_engine) = &evt.files {
let files = file_engine.files();
for file_name in &files {
println!("{}", file_name);
// Do something with the folder path
}
}
}
}
// ANCHOR_END: rsx
})
}
// ANCHOR_END: component

0 comments on commit 1119f27

Please sign in to comment.