How to add an image in Yew?

3.7k views Asked by At

I am building a simple web app with Rust and I am trying to display an image to the website. But I can't add that image.

I am using Rust with a framework called Yew and with a tool Trunk.

I have successfully linked the .scss file to my website with Trunk. As they described in their documentation.

index.html

<!DOCTYPE HTML> 
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Yew Development</title>
    <link data-trunk="" rel="scss" href="main.scss"> <!-- Successfull linked to this file -->
</head>

<body></body>

</html>

The .scss file does its work successfully.

But how can I display an image with Rust file with the html! macro?

main.rs

use yew::prelude::*;

fn main() {
    yew::start_app::<App>();
}

#[function_component(App)]
fn app() -> Html {
    html! {
        <>
            <h1> {"Hello world!"}</h1>
            <link data-trunk="true" rel="copy-file" href="img/rust.png"/> // doesn't work
            <img data-trunk="true" src="img/rust.png" alt="rust image"/> // doesn't work
            <img src="img/rust.png" alt="rust image"/> // doesn't work
        </>
    }
}

Trunk's docs about how to add image.

But the doc wasn't helpful for me.

3

There are 3 answers

0
Denys Séguret On

What you must do is instruct trunk to copy your static assets into the dist directory.

Let's suppose you have a directory called img with all the images, next to your src directory at the root of your project:

/home/me/code/my-yew-test
 ├──Cargo.lock 
 ├──Cargo.toml 
 ├──index.html 
 ├──src 
 │  └──main.rs 
 └──img 
    └──rust.png 

Add this line to your index.html header:

<link data-trunk rel="copy-dir" href="img">

This line won't be present in the production index.html file, it's only an instruction for trunk.

Now the files of the img directory will be served by trunk (and copied into the dist directory for production) so you can have this link in your html! macro:

<img src="img/rust.png" alt="rust image"/> 

data-trunk attributes here would make no sense: trunk only reads and parses the index.html file, it doesn't see what's generated client side by the wasm code produced by the html! macro.

Your dist directory will look like this:

    /home/me/code/my-yew-test
     ├──Cargo.lock 
     ├──Cargo.toml 
     ├──dist 
     │  ├──dysp-8a629f50b28a5e37.css 
     │  ├──index-8c2be3ebf3bd7075.js 
     │  ├──index-8c2be3ebf3bd7075_bg.wasm 
     │  ├──index.html 
     │  └──img
     │     └──rust.png
     ├──index.html 
     ├──src 
     │  └──main.rs 
     └──img 
        └──rust.png 
0
E_net4 On

All <link data-trunk ... /> elements must be in the static HTML files (such as index.html), not in the dynamically generated virtual DOM nodes via html!. This is because Trunk runs as a back-end process to determine what exactly is distributed as part of the main application, and this is a process which must be done in advance.

Attempting to add a link element afterwards would be an attempt to include an asset as part of the application after Trunk already did its job of copying and processing the expected assets, so it does not work. Instead, define all assets that you are going to need in your index.html, preferably in the head element, then you will be free to use them in your application by path (e.g. image/rust.png).

0
Osoro On

What you should do is make the path relative. Say this is your directory structure:

/home/me/code/my-yew-test
├── Cargo.lock
├── Cargo.toml
├── index.html
├── img
│   └── rust.png
├── README.md
└── src
    └── main.rs

In the index.html file you should add a relative folder/file path to the resource you want compied. For copying the whole folder and using the image in main.rs:

<!--in index.html-->
<link data-trunk rel="copy-dir" href="./img"/>
// in main.rs
html!{
    <img src="img/rust.png" alt="rust image"/> 
}