How to display image using address in DB using Vue.js? - html

I'm trying to display an image saved with Django REST. When saving, the path that is indicated in the database is "user_avatars/user1/avatar1.jpg".
When I upload an object from the database to the frontend (Vue.js 3) using the API, the address is displayed as "http://127.0.0.1:8000/uploads/user_avatars/user1/avatar1.jpg"
Here you can see that I use "/uploads/" as the MEDIA_URL folder in Django. However, trying to display an image from this link does nothing:
<img src="http://127.0.0.1:8000/uploads/user_avatars/user1/avatar1.jpg">
I tried to do it in several ways, and found one working option:
<img src="../../../uploads/user_avatars/user1/avatar1.jpg" />
Surprisingly, if I try to construct the same path using Vue, nothing loads:
<img :src="getAvatarURL" />
There the "getAvatarURL" function simply returns the string above:
getAvatarURL(){
return "../../../uploads/user_avatars/user1/avatar1.jpg"
At the same time, the only working option, where I manually entered the path to the file, apparently uploads it to the front-end server and only then displays it, because as I noticed in chrome devTools, the path to the file changes to this:
<img src="http://127.0.0.1:8080/img/avatar1.0cb5eef6.jpg" />
I absolutely lost in this. I've tried to change vue config file to change folder where to store images, but it also didn't help.
Please, tell me how to use the link provided from the database correctly?

This going to boil down to how you have your build tools set up, and how you are storing your images.
Maybe not store the full path, but a file name, and have the path be something like public/assets/images/ + filename.ext
Here is how I have my setup. I use Webpack to compile:
webpack.config.js
module.exports = {
entry: { ... },
module: {
rules: [
{
test: /\.(png|jpe?g|gif|bmp)$/i,
type: 'asset/resource'
generator: {
filename: './assets/images/[name][ext]
}
}
]
}
}
Then inside my src file i keep my images in a folder called assets/images. which when compile copies them to public/assets/images.
Then inside my Vue files i can import the file
<script lang="ts">
import { defineComponent, ref } from "vue"
import avatar from '#/assets/images/avatar1.png'
export default defineComponent({
name: 'sidebar-user',
setup() {
return { avatar }
}
})
</script>
and return it to template where it looks like this:
<template>
<img :src="avatar" alt="avatar" />
</template>

Related

Svelte - routing , When I try entering any url I only get "No webpage was found" error

Using "svelte-routing" because I need to load a single page from lots of different urls , with the different urls serving as parameters.
For example if a client loads into my-sight/123 the sight needs to load the app.svelte component while passing 123 as a parameter.
The Problem is that whatever url I enter after the "my-sight/" I always get a "No webpage was found" page.
App.svelte:
<script script lang="ts">
import MenuGenerator from './components/MenuSections/MenuGenerator.svelte';
import { Router, Route } from 'svelte-routing';
</script>
<Router>
<Route path="/:accomodation" component={MenuGenerator} />
</Router>
MenuGenerator.svelte:
<script script lang="ts">
export let accomodation: string;
console.log('hello ', accomodation);
</script>
I've tested this on https://codesandbox.io/s/svelte-routing-forked-ztddj , just add anything after the / in the url and press enter and the same text is in the console.
Edit: We have QR codes and NFC tags, their urls are set and cannot be changed. The urls are my-sight/{qr_code} . I need routing that would redirect every possible url to home and pass in the {qr_code} as a value.
With that last edit / comment, your use case makes a whole lot more sense.
You can use window.location.pathname in the browser to identify the QR Code within the URL.
<script>
import { Router, Route } from "svelte-routing";
import Home from "./routes/Home.svelte";
import { onMount } from "svelte";
onMount(()=>{
let qr_code = window.location.pathname.substring(1); // dump leading '/'
console.log("qr_code: ", qr_code);
})
</script>
<Router>
<div class="box">
<Route path="/:id" component={Home} />
</div>
</Router>
(edit) This answer specifically address the need to" I need routing that would redirect every possible url to home and pass in the {qr_code} as a value.
It sounds now, like that is only a partial requirement. (/edit)
SOLVED !!!
I needed to uncomment a line of code in my snowpack config.
The line of code is:
//{ match: 'routes', src: '.*', dest: '/index.html' },
Tnx for the help !

Webpack to build HTML page based on different HTML files [duplicate]

I am using Webpack to compile my scripts and HTML (using html-webpack-plugin). The thing is, I have 5 HTML files that contains the same parts and I want to move these parts to separate .html files and then include these parts in every HTML file. This way, if I will change these smaller HTML files, it will recompile every HTML file to represent these changes.
Webpack does this for .js files by default, but can I use something like that for HTML files?
You can use <%= require('html!./partial.html') %> in your template. Example here: https://github.com/jantimon/html-webpack-plugin/blob/master/examples/custom-template/template.html
Another slightly different solution.
Using html-loader with interpolate option.
https://github.com/webpack-contrib/html-loader#interpolation
{ test: /\.(html)$/,
include: path.join(__dirname, 'src/views'),
use: {
loader: 'html-loader',
options: {
interpolate: true
}
}
}
And then in html pages you can import partials html and javascript variables.
<!-- Importing top <head> section -->
${require('./partials/top.html')}
<title>Home</title>
</head>
<body>
<!-- Importing navbar -->
${require('./partials/nav.html')}
<!-- Importing variable from javascript file -->
<h1>${require('../js/html-variables.js').hello}</h1>
<!-- Importing footer -->
${require('./partials/footer.html')}
</body>
html-variables.js looks like this:
const hello = 'Hello!';
const bye = 'Bye!';
export {hello, bye}
The only downside is that you can't import other variables from HtmlWebpackPlugin like this <%= htmlWebpackPlugin.options.title %> (at least I can't find a way to import them) but for me it's not an issue, just write the title in your html or use a separate javascript file for handle variables.
Check out Partials for HTML Webpack Plugin for something a little more elegant. It lets you set up HTML files and include them similar to what you're looking for simply like:
plugins: [
new HtmlWebpackPlugin(),
new HtmlWebpackPartialsPlugin({
path: './path/to/partials/body.html'
})
]
Also configurable for where it gets added such as head vs body, opening vs closing, and lets you pass in variables.
You can use html-loader and posthtml. Then you can use the posthtml-include plugin.
const postHtml = require('posthtml');
const postHtmlInclude = require('posthtml-include');
{
test: /\.html$/,
use: {
loader: 'html-loader',
options: {
esModule: false,
preprocessor: async (content, loaderContext) => {
try {
return await postHtml(postHtmlInclude()).process(content)).html;
} catch (error) {
loaderContext.emitError(error);
return content;
}
},
},
},
},

EmberJS: How to load assets relative to rootURL or load assets using absolute path

this might be a pretty common question but what I found on google does not help me.
I have a emberJs Project with all assets(images, etc) in
my-ember-project/public/assets/images/
everything works fine when i load the assets from homepage which is the root URL "/" or localhost:4200
for example in my homepage
I have a component with img tag which looks like this
<img src="assets/images/articles/article-1.jpg"/>
on another page with url localhost:4200**/articles/** I also load the same image with the same tag
but from what I've seen it tried to load the image from localhost:4200/articles/assets/images/articles/article-1.jpg and not from the correct path localhost:4200/assets/images/articles/article-1.jpg
adding "/" before "assets/images/" works for me if I'm trying to host my project on root folder
but when I need to host my project on subdirectory so my url (www.mydomain.com/ember-project-here/)
how do I load my assets from absolute path or relative to my settings of rootURL
adding {{rootURL}} seems to do nothing to me
It seems, {{rootURL}} does not work in hbs files (long time ago I used to think it does).
{{env 'rootURL'}} should work, where env is a helper defined like this:
import { get } from '#ember/object';
import { helper } from '#ember/component/helper';
import ENV from 'project-name/config/environment';
export default helper(function([path]) {
return get(ENV, path);
});
you can add a path helper:
import { helper } from '#ember/component/helper';
import ENV from 'project-name/config/environment';
export default helper(function([path]) {
return path.replace(/^~\//, ENV.rootURL);
});
The you can do:
<img src={{path "~/assets/images/articles/article-1.jpg"}} />
This is nice because you can also use variables:
<img src={{path this.myPath}} />
and myPath:
get myPath() {
return `~/assets/images/${this.args.iconName}.jpg`;
}
You've done a good research on this front. Yes, rootURL is the one you want to add to your project since you are deploying your application to a subfolder.
rootURL can be added to any Ember app using the config/environment.js file.
// config/environment.js
module.exports = function(environment) {
var ENV = {
// other configs...
rootURL: '/ember-project-here/',
};
}
The official guide can give you some additional info!

Stylesheet not loaded because of MIME-type Angular application

I'm Working on a Angular 6.x application where i'm trying to change theme (dynamically).
The CLI compile everything properly but in developer console im getting this error message.
Refused to apply style from
'http://localhost:4200/vendor/theme-light.css' because its MIME type
('text/html') is not a supported stylesheet MIME type, and strict MIME
checking is enabled.
My file structure looks like this, the path is correct
project
|-src
|-vendor
|-theme-light.css
|theme-dark.css
My theme changing code looks this
import { Component, Inject, PLATFORM_ID } from '#angular/core';
import { DOCUMENT, isPlatformBrowser } from '#angular/common';
#Component({
..
..
})
linkRef: HTMLLinkElement;
themes = [
{ name: 'Light', href: '../vendor/theme-light.css' },
{ name: 'Dark', href: '../vendor/theme-dark.css' }
];
constructor(#Inject(DOCUMENT) private document: Document, #Inject(PLATFORM_ID) private platformId: Object) {
if (isPlatformBrowser(this.platformId)) {
let theme = this.themes[0];
try {
const stored = localStorage.getItem('theme');
if (stored) {
theme = JSON.parse(stored);
}
} catch (e) {
}
this.linkRef = this.document.createElement('link');
this.linkRef.rel = 'stylesheet';
this.linkRef.href = theme.href;
this.document.querySelector('head').appendChild(this.linkRef);
}
}
setTheme(theme) {
localStorage.setItem('theme', JSON.stringify(theme));
this.linkRef.href = theme.href;
}
Now, I don't really understand why this happens. Is am i missing something ? Feel free to ask for more details if needed.
Any help will be really appreciated.
Thanks
Looks like the href is wrong.
There is a good answer to a different question exactly like yours:
The usual reason for this error message is that when the browser tries to load that resource, the server returns an HTML page instead, for example if your router catches unknown paths and displays a default page without a 404 error. Of course that means the path does not return the expected CSS file / image / icon / whatever...
The solution is to find the correct path and router configuration so that you get your plain CSS file / image / etc. when accessing that path.
In your case it's the css href.
Finally figured out Im giving the wrong path on my path configuration href: '../vendor/theme-light.css' thats returns http://localhost:4200/vendor/theme-light.css on the browser which is not the correct path.
Solution
themes = [
//added the missing src ( source root)
{ name: 'Light', href: '../src/vendor/theme-light.css' },
{ name: 'Dark', href: '../src/vendor/theme-dark.css' }
];
Thank You for your answers
when you're using a static folder , please make sure to use "/" . Let's say for example assets is our static folder , we want the image folder which is under the assets , so you type this src="image/img1.png" , that's wrong you have to add "/" ,,, so it will be like this src="/image/img1.png"
Found this answer here Proper solution
The issue could be with a CSS library starting with comments. While on dev, We do not minify files and We don't remove comments, this meant that the stylesheet started with some comments, causing it to be seen as something different from css.
Removing the library and putting it into vendor file (which is ALWAYS minified without comments) solved the issue.
you have to change the place of your file css into the directory assets assets/style.css
and then put these path in your file index.html src/index.html
<link rel="stylesheet" type="text/css" href="assets/style.css" />
in addition you have to modify to file angular.json in styles
"styles": [
"src/assets/style.css",
"./node_modules/materialize-css/dist/css/materialize.min.css",
],

How to download a locally stored file in VueJS

I have an upload system and I am trying to supply a sample template for users. I have a template stored locally in a subfolder in assets, I would like to access that in my VueJS component and display a link to it on the page. These are the applicaple parts of the file structure:
├──app
│ └──Components
│ └──Uploader.vue
└──assets
└──files
└──Template_Upload.csv
In Uploader.vue I have this line:
<a v-bind:href="item.loc" download>{{item.title}}</a>
And in the export I have this line
data() {
return {
item: {title: 'Upload Template', loc: require('../../assets/files/Template_Upload.csv')}
}
This method works if I have an image. Upon clicking on the link, it downloads the image. However, if I use a .csv or a .xlsx file, errors are thrown upon opening the page. I've tried using
import fileTemplate from "../../assets/files/FileTemplate.csv";
As well, and using fileTemplate as the loc property. This also works if I use a picture. But I'm not able to bring in a document. Is this a limitation I can't get past or is there a different method I can try?
I've also gone into Visual Studio (in other words, the .csproj file), and set the Template_Upload.csv Build Action setting is set to "Content" and the Copy to Ouput Directory setting is set to "Copy Always".
These are the resources I have primarily used thus far:
How to import and use image in a Vue single file component?
What are the various "Build action" settings in Visual Studio project properties and what do they do?
For anyone which doesnt want to use webpack, I solved this issue:
create a folder called files in public
I moved there the files I wanted to download
and Voila, WORKED.
<a href="/files/book.pdf" download>DOWNLOAD</a>
Thanks OverCoder, the solution was indeed to add a CSV Loader in order that adds the locally stored files to the webpack server. For anyone else using webpack, I added this module to my webpack.config.js file:
{
test: /\.(csv|xlsx|xls)$/,
loader: 'file-loader',
options: {
name: `files/[name].[ext]`
}
}
Then I could reference the file easily like this in my template,
<a href="/files/Template_Upload.csv" download>File Template</a>
or this
<a :href="item.loc" download>File Template</a>
using the same data return as I said. Using the require statement with the loader puts the "required" files into the wwwroot/files folder when the project builds. Thanks again, OverCoder, this saved me a lot of time.
Just an extension to the #Judd's answer. If you don't have a webpack.config.js, you can use the vue.config.js file. (just create it in the root, if it doesn't exist)
vue.config.js
module.exports = {
configureWebpack: {
module: {
rules: [
{
test: /\.(csv|xlsx|xls)$/,
loader: 'file-loader',
options: {
name: `files/[name].[ext]`
}
}
],
},
},
};
This works for me;
<a href="../../assets/files/FileTemplate.csv" download>Download</a>
It behaves nicely even in dialogs.
I was on Laravel, and I follow this tuto to get mine working:
create an FileController, add a download method
public function downloadFile($file){
$path = public_path().'/app/upload-folder/'.$file; // or storage_path() if needed
$header = [
'Content-Type' => 'application/*',
];
return response()->download($path, $file, $header);
}
create an api entry point in api.php
Route::get('download/upload-folder/{file}', 'FileController#downloadFile');
create a method which uses axios
async downloadTemplateFile(file){
axios.get('/download/template/file/'+file, {responseType: 'arraybuffer'}).then(res=>{
let blob = new Blob([res.data], {type:'application/*'})
let link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = file
link._target = 'blank'
link.click();
})
}
call from vue template
<li>Download the CSV template here</li>
Hope this will helps others ;)
Place the file you want to download in the public folder as it is the root folder of your application.
File Structure Image ->
Image Link
Give the href link as below :
<a :href="'/files/SampleFile.xlsx'" class="btn btn-primary" download>Sample File</a>
You can provide any file in the folder structure. For example : .pdf, .xlsx, .png etc
Please note, give the href as :href with file path as " 'your file path' "
Tested and Working on Vue3
Try this:
Download
Try this way and it is with a button:
<a href="/files/Template_Upload.csv" download>
<button class="btn btn-primary">Download</button>
</a>