How can I use a file.js in a component vue - javascript

I tried to use prueba.js in one of the components of my app (InputSwap.vue), in which there is a button ('console.log'). I want to use this file using that button, but the app showed me this error:
enter image description here
prueba.js let me see the data in the console by clicking the button.
The data was saved with window.localStorage:
window.localStorage.setItem('data_input', JSON.stringify(data));
where am I wrong?
prueba.js :
export default {
infoPrueba() {
var data = (JSON.parse(window.localStorage.getItem('data_input')))
console.log(data)
}
}
InputSwap.vue:
<template>
<div class="card-action">
<Button v-on:click="prueba()"
v-bind:style="{'margin-left' : '5px', background : '#52368c'}"
btext="Console.log" icon="code"
/>
</div>
</template>
<script>
import Button from './Button'
import * as prueba from './prueba.js' // I have prueba.js in components folder
export default {
name: 'InputSwap',
components: {Button},
methods: {
prueba: async function () {
prueba.infoPrueba()
},
},
}
</script>

Thanks to x-rw, I solved this problem:
I changed import * as prueba from './prueba.js' to import {infoPueba} from './prueba.js'
and I wrote this code in prueba.js:
export const infoPrueba = () => {
var data = (JSON.parse(window.localStorage.getItem('data_input')))
console.log(data)
}

Related

Dynamic import image in Vue-3

I'm trying to show a dynamically imported image, but it's not working with the error
'Cannot find module'
This is my component
<template>
<div class="footer">
<div v-for="footerItem in getters" :key="footerItem.id">
<img :src="methods.requireImage(footerItem.icon)" alt="">
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { useStore } from '#/store'
import { requireImage } from '#/modules/images'
export default defineComponent({
name: 'Footer',
setup () {
const store = useStore()
const methods = {
requireImage
}
return {
getters: store.getters.getFooterItems,
methods
}
}
})
</script>
And this is module
export const requireImage = async (link: string) => {
// return require(link)
const image = await import(link)
return image
// const images = require.context('../assets', false)
// return images('color-circle.svg')
}
Commented out code not working
If you pass the full path to require in a variable, Webpack can't load the image. This is roughly because it's a build-time tool, and the path is created at runtime. If you hard-code at least some of the path though, that will be sufficient:
export const requireImage = link => {
return require(`#/assets/${link}`);
}
Note: Removed the unnecessary async or the return value would be a promise
Your variable footerItem.icon should just contain the filename color-circle.svg now that some of the path is hard-coded in the call to require. With that done, you can use the method in the template as you wanted:
<img :src="methods.requireImage(footerItem.icon)" alt="">
Be aware that at the moment your wrapper method is unnecessary because you could get the same result from:
<img :src="require(`#/assets/${footerItem.icon}`)">

Vue composition API calling child component method

TLDR; In v2, this.$refs does the job but how can I do that in v3 composition api?
I am trying to use CustomUpload feature of PrimeVue in Vue3, but that API does not clear the upload files after uploading them and I need to call clear() method of the child component in the parent component to clear the files and refresh the button.
Here's my App.vue
<template>
<FileUpload
name="upload"
url="/"
mode="basic"
:auto="true"
:maxFileSize="26214400"
:fileLimit="1"
:customUpload="true"
#uploader="upload"
/>
<Button name="lalaal">qweeq</Button>
</template>
<script>
import FileUpload from 'primevue/fileupload'
export default {
setup() {
const upload = e => {
console.log('testing', e)
}
return { upload }
},
components: {
FileUpload
}
}
</script>
Thanks
You could use template ref then use uploadFile.value instead of this.$refs.uploadFile :
<template>
<FileUpload
ref="uploadFile"
name="upload"
url="/"
mode="basic"
:auto="true"
:maxFileSize="26214400"
:fileLimit="1"
:customUpload="true"
#uploader="upload"
/>
<Button name="lalaal">qweeq</Button>
</template>
<script>
import FileUpload from 'primevue/fileupload'
import {ref} from "vue";
export default {
setup() {
const uploadFile=ref(null)
const upload = e => {
console.log('testing', e)
}
return { upload,uploadFile}
},
components: {
FileUpload
}
}
</script>

VueJS; wait for element before running local JavaScript File

I have a few components, javascript, and elements that needs to be ran in a certain order.
1st - opensheetmusicdisplay.min.js which I have in my index.html file. This isn't an issue.
2nd - <div id="xml">
3rd - xml-loader.js which depends on both the "xml" div and opensheetmusicdisplay.min,js
This is the index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<script rel="preload" src="<%= BASE_URL %>js/osmd/opensheetmusicdisplay.min.js"></script>
</head>
<body>
<div id="xml2">words go here</div>
<div id="app"></div>
</body>
</html>
And this is the JavaScript part I'm attempting to test:
window.onload = function() {
alert("xx == ", document.getElementById("xml2"));
}
alert("xx2 == ", document.getElementById("xml2"));
alert(JSON.stringify(opensheetmusicdisplay, null, 1));
When I run this, they both instances of "xml2" show blanks. The opensheetmusicdisplay does show data, which means it is reading from the source in the head section in index.html
It was pointed out to me in the comments that alert only take one argument. That's a mistake that I'm going to let sit for the moment. The error in the console is TypeError: document.getElementById(...) is null.
Now, this is the main.js. There are a lot of comments because of my various ideas:
// vue imports and config
import Vue from 'vue'
import App from '#/App'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
Vue.config.productionTip = false
// page imports
import Notation from '#/components/Notation'
import HomePage from '#/components/HomePage'
// component imports and registration
import { FoundationCSS } from '#/../node_modules/foundation-sites/dist/css/foundation.min.css'
Vue.component('foundation-css', FoundationCSS)
import SideNav from '#/components/SideNav'
Vue.component('side-nav', SideNav);
// import * as Osmd from '#/../public/js/osmd/opensheetmusicdisplay.min.js'
// Vue.component('osmd-js', Osmd)
// import { OsmdJs } from '#/components/Osmd'
import * as XmlJs from '#/../public/js/osmd/xml-loader.js'
Vue.component('xml-js', XmlJs)
// import XLoad from '#/components/XmlLoader'
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/',
components: {
maininfo: HomePage
}
},
{ path: '/chromatic-scales/c-chromatic-scale',
components: {
maininfo: Notation// ,
// xmlloader: XLoad
}
}
]
})
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
I registered XmlJs as global because this is the only way out of 100 things that actually works. I then embed it in Notation.vue like so:
<template>
<div>
<div id="xml">
{{ notation.data }}
</div>
<xml-js />
</div>
</template>
<script>
import axios from 'axios'
export default ({
data () {
return {
notation: null,
}
},
mounted () {
axios
.get('http://localhost:3000/chromatic-scales/c-chromatic-scale')
.then(result => (this.notation = result))
}})
</script>
<style scoped></style>
The last file is the meat and potatoes of what I'm trying to do. The xml-loader.js slurps the data from <div id="xml"> and does whatever magic the program does in order to render the output I want. The issue is that there doesn't seem to be anyway to wait for the stuff in {{ notation.data }}.
I am new to using vuejs and front-end javascript frameworks in general. I do recognize the code is probably not optimal at this time.
There is race condition where DOM element is not available at the time when it's accessed. The solution is to not access DOM elements created by Vue outside of it. DOM element is ready for use only after asynchronous request:
<template>
<div>
<div ref="xml" id="xml">
{{ notation.data }}
</div>
<xml-js />
</div>
</template>
<script>
import axios from 'axios'
export default ({
data () {
return {
notation: null,
}
},
async mounted () {
const result = await axios
.get('http://localhost:3000/chromatic-scales/c-chromatic-scale')
this.notation = result;
this.$nextTick(); // wait for re-render
renderXml(this.$ref.xml); // pass DOM element to third-party renderer
}})
You can import xml-loader.js into the Notation.vue as a function. Then you can simply do something like this:
mounted () {
axios.get(PATH).then(result => {
this.notation = result
let xmlResult = loadXML(result)
doSomethingWithResult(xmlResult)
}
},
methods: {
doSomethingWithResult (result) {
// do something
}
}

Image Overlay plugin for FilePond Vue

I want a review button on image, but I don't find attribute.
I set the imagePreviewMarkupShow = true but it didn't work.
Package here
My Template
<template>
<div id="app">
<file-pond
name="test"
ref="pond"
max-files="4"
label-idle="Drop files here..."
:allow-multiple="true"
accepted-file-types="image/jpeg, image/png"
:files="myFiles"
v-on:init="handleFilePondInit"
allowImagePreview ="false"
/>
</div>
</template>
My Script
import vueFilePond from 'vue-filepond';
import 'filepond/dist/filepond.min.css';
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css';
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
import FilePondPluginImageOverlay from 'filepond-plugin-image-overlay';
// Create component
const FilePond = vueFilePond(FilePondPluginFileValidateType, FilePondPluginImagePreview,FilePondPluginImageOverlay);
export default {
name: 'app',
data: function() {
return { myFiles: [] };
},
methods: {
handleFilePondInit: function() {
console.log('FilePond has initialized');
// this.$refs.pond.getFiles();
// FilePond instance methods are available on `this.$refs.pond`
}
},
components: {
FilePond
}
};
How do I add that button?
I was also struggling with this problem.
The solution is to import CSS.
import 'filepond-plugin-image-overlay/dist/filepond-plugin-image-overlay.min.css'
This is not mentioned in Github.

Vuejs call other component's method with parameter

I have two components, the first one is for uploading a file and the second one to Show a file. Inside my Upload Component I would like to call the Preview Component and add a Parameter so that a method inside the Preview Component uses a value which is created inside the Upload Component.
So far I have done this:
UploadComponent.vue
<template>
…
<button #click="upload"></button>
<preview-component :url="this.location"></preview-component>
</template >
<script>
import PreviewComponent from '#/js/components/PreviewComponent';
export default {
components: {
'preview-component': PreviewComponent
},
props: ['url'],
data () {
return {
// ...
location: ''
}
},
methods: {
upload() {
// ... upload stuff then update the global var location
this.location = response.data.location;
},
}
}
</script>
This is my Preview Component:
<template>
<div id="body">
///...
</div>
</template>
<script>
export default {
props: ['url'],
methods: {
loadPdf (url) {
//
},
}
}
</script>
So far I am getting the error that url is not defined, so it actually does not sent the url from the UploadCOmponent to the PreviewComponent, how do I manage to sent it?
You got a ninja this in your UploadComponent's template.
It should be <preview-component :url="location"></preview-component>

Categories