DEV Community

Cover image for Experience WebForms Core Technology in Rust; File Deletion Example
Elanat Framework
Elanat Framework

Posted on

Experience WebForms Core Technology in Rust; File Deletion Example

For Rust developers, we have good news: From now on, you can also experience WebForms Core technology in Rust. At Elanat, we have updated the WebForms class of the Rust programming language to the latest version of the WebFormsJS library, version 1.6.

WebForms Core is an automated and advanced technology for simple management of HTML tags on the server. In this technology, data is sent to the server completely faithfully to HTML (and is done via WebFormsJS), but the state of the page remains static. The server also sends INI data via the WebForms class to the WebFormsJS library on the client. WebForms Core technology allows you to manipulate tags offline in serverless scenarios. To use this technology, you need to add the WebFormsJS library and the WebForms class associated with your desired programming language to your system.

Download Links

You can download the WebForms class for the Rust programming language from the link below.

web_forms.rs

To download the latest version of WebFormsJS, visit the following link.

Download WebFormsJS

Example: Using WebForms Core in Actix Web

The code below the page is the view and the lower code you see is the server code related to the Rust programming language created under the Actix Web framework. This is an example to display a list of image files and the ability to delete them via a web page. In this example, the user views the images on the web page and has the ability to delete them. In this example, when the user clicks on the red button, the image file is deleted from the server and subsequently, on the web page, the tag containing the image, the image name, and the delete button are deleted and a deletion message is shown to the user for 3 seconds.

This file is an HTML template that displays a list of files and a form to delete them. It uses Tera templating engine for rendering dynamic content.

View (index.html)

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
    <script type="text/javascript" src="/static/script/web-forms.js"></script>
    <style>
    img
    {
        width: 300px;
        padding-top: 10px;
    }
    input[type="submit"]
    {
        border-radius: 15px;
        padding: 10px;
        font-size: 0px;
        background-color: red;
        margin: 0px 0px 40px 275px;
    }
    </style>
</head>
<body>
    <h1>WebForms Core Technology in Rust</h1>
    <form method="POST" action="/">
        <ul>
            {% for file in files %}
            <li>
                <b>{{ file }}</b><br>
                <img id="file_{{ loop.index }}" src="/static/file/{{ file }}"><br>
                <input type="submit" name="Delete" value="{{ loop.index }}|{{ file }}">
            </li>
            {% endfor %}
        </ul>
    </form>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

In the code below, the "main" method is for setting the initial configuration. The "index" method is also created to call the "index.html" page and create a list of image files.
The "handle_post" method has been added to delete the image file and use WebForms Core technology.

Rust code

use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use tera::{Context, Tera};
use std::fs;
use std::path::Path;
use std::sync::Arc;

use actix_files as actix_fs;

mod web_forms;
use crate::web_forms::{WebForms, InputPlace};

#[derive(Clone)]
struct AppState {
    tera: Arc<Tera>,
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    // Initialize Tera template engine
    let tera = Tera::new("templates/**/*.html").unwrap();

    // Start Actix Web server
    HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(AppState {
                tera: Arc::new(tera.clone()),
            }))
            .route("/", web::get().to(index))
            .route("/", web::post().to(handle_post))
            .service(actix_fs::Files::new("/static", "./static").show_files_listing())
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

async fn index(state: web::Data<AppState>) -> impl Responder {
    let dir_path = Path::new("static/file");
    let mut file_list = Vec::new();

    // Check if the directory exists
    if dir_path.exists() && dir_path.is_dir() {
        // Read the directory and collect file names
        match fs::read_dir(dir_path) {
            Ok(entries) => {
                for entry in entries {
                    if let Ok(entry) = entry {
                        if let Some(file_name) = entry.file_name().to_str() {
                            file_list.push(file_name.to_string());
                        }
                    }
                }
            }
            Err(e) => eprintln!("Error reading directory: {}", e),
        }
    }

    let mut ctx = Context::new();
    ctx.insert("title", "Welcome to WebForms Core");
    ctx.insert("files", &file_list);

    let rendered = state.tera.render("index.html", &ctx).unwrap_or_else(|e| {
        eprintln!("Failed to render template: {}", e);
        String::new()
    });
    HttpResponse::Ok().content_type("text/html").body(rendered)
}

async fn handle_post(params: web::Form<Params>, state: web::Data<AppState>) -> impl Responder {
    let file_index = &params.Delete;
    let parts: Vec<&str> = file_index.split('|').collect();

    // Using WebForms Core to delete row
    let mut form = WebForms::new();
    form.add_tag_to_up(InputPlace::tag("form").as_str(), "h3".to_string(), "".to_string());
    form.set_background_color(InputPlace::tag("h3").as_str(), "orange".to_string());

    // Create a longer-lived value for the file path
    let file_path_str = format!("static/file/{}", parts[1]);
    let file_path = Path::new(&file_path_str);

    // Attempt to remove the file
    match fs::remove_file(file_path) {
        Ok(_) => form.set_text(InputPlace::tag("h3").as_str(), "File removed successfully.".to_string()),
        Err(e) => form.set_text(InputPlace::tag("h3").as_str(), format!("Failed to remove file: {}", file_path.display())),
    }

    form.delete(InputPlace::tag("h3").as_str());
    form.assign_delay(3.0,-1);

    form.delete(format!("/file_{}", parts[0]).as_str());

    HttpResponse::Ok().body(form.response())
}

#[derive(serde::Deserialize)]
struct Params {
    Delete: String,
}
Enter fullscreen mode Exit fullscreen mode

The GIF image below shows how the above code works.

WebForms Core

Initialization

mod web_forms;
use crate::web_forms::{WebForms, InputPlace};
Enter fullscreen mode Exit fullscreen mode

Delete image

Since we want to use the WebForms core technology in the Rust programming language, we need to call this class as follows.

If you look at the view page, you will notice that the data is sent via the POST method. The "handle_post" method is also called to respond to the data sent via the POST method.
In the "handle_post" method, the data value of the input tag, which is of the submit type, is first read. Here, there are two data values, one is the index and the other is the file name. These values ​​are separated and placed in an array called "parts".
Note: Sending multiple values ​​via HTML is a common practice. The submit tag is initialized as follows after rendering:

<input type="submit" name="Delete" value="1|pic 1.jpg">
Enter fullscreen mode Exit fullscreen mode

Following the codes of the "handle_post" method, the file is physically deleted. A new instance of the WebForms class is created and using the WebForms class, an h3 tag is added to the beginning of the single form and its color is changed to orange. Then the text "File removed successfully." is placed inside the h3 tag and then the command to remove the h3 tag after 3 seconds is added. Finally, the command to remove the parent tag for the img tag is added via its id value.

async fn handle_post(params: web::Form<Params>, state: web::Data<AppState>) -> impl Responder {
    let file_index = &params.Delete;
    let parts: Vec<&str> = file_index.split('|').collect();

    // Using WebForms Core to delete row
    let mut form = WebForms::new();
    form.add_tag_to_up(InputPlace::tag("form").as_str(), "h3".to_string(), "".to_string());
    form.set_background_color(InputPlace::tag("h3").as_str(), "orange".to_string());

    // Create a longer-lived value for the file path
    let file_path_str = format!("static/file/{}", parts[1]);
    let file_path = Path::new(&file_path_str);

    // Attempt to remove the file
    match fs::remove_file(file_path) {
        Ok(_) => form.set_text(InputPlace::tag("h3").as_str(), "File removed successfully.".to_string()),
        Err(e) => form.set_text(InputPlace::tag("h3").as_str(), format!("Failed to remove file: {}", file_path.display())),
    }

    form.delete(InputPlace::tag("h3").as_str());
    form.assign_delay(3.0,-1);

    form.delete(format!("/file_{}", parts[0]).as_str());

    HttpResponse::Ok().body(form.response())
}

#[derive(serde::Deserialize)]
struct Params {
    Delete: String,
}
Enter fullscreen mode Exit fullscreen mode

At the end of the method, the response is sent via the response method.

What is sent from the client to the server?

As we mentioned earlier, in WebForms Core technology, data is sent as if it were an HTML page form submission.

Example:

Delete=1|pic 1.jpg
Enter fullscreen mode Exit fullscreen mode

What does the server respond to the client?

The server response is also based on the INI pattern.

Example:

[web-forms]
ut<form>=h3
bc<h3>=orange
st<h3>=File removed successfully.
:3)de<h3>=1
de/file_1=1
Enter fullscreen mode Exit fullscreen mode

You can get the sample code in link below.
WebForms.rs Update to WebFormsJS 1.6

Conclusion

WebForms Core Technology in Rust opens up exciting possibilities for Rust developers by integrating an automated and advanced way to manage HTML tags on the server. Leveraging the latest version of the WebFormsJS library, version 1.6, WebForms Core offers a seamless and efficient way to manipulate tags offline in serverless scenarios.

The provided example demonstrates a practical implementation using Actix Web to display and delete image files via a web page. The user-friendly interface, combined with the robust capabilities of WebForms Core, showcases the power and flexibility of this technology.

By incorporating WebForms Core into your Rust projects, you can enhance your web development experience with automated tag management, making it easier to build dynamic and interactive web applications. Download the WebForms class for Rust and the WebFormsJS library to get started and explore the full potential of this innovative technology.

Happy coding!

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free β†’

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay