Vuejs if image exists - vuejs2

I am new to vuejs, i have a mounted section to search for an image:
mounted () {
this.UserImage = localStorage.Image
this.UserName = localStorage.Name
},
When i have no image this.UserImage returns the string: data:image/jpeg;base64,
What can i use to compare and using v-if v-else display some default image in case i did not found an image ?
My try was :
mounted () {
this.$nextTick(function () {
this.UserImage = localStorage.Image
this.UserName = localStorage.Name
})
},

I'd have done something like this :
mounted () {
this.UserImage = localStorage.Image !== 'data:image/jpeg;base64,' ? localStorage.Image : defaultPath
},
It'd help keeping the template clean.
I would set the image that doesn't exist to an empty string (instead of data:image/jpeg;base64,). That way you could have a shorter implicit if statement :
mounted () {
this.UserImage = localStorage.Image || defaultPath
},

You can use something like this:
<img :src="userImage" v-if="userImage !== 'data:image/jpeg;base64,'">
<img src="defaultImagePath" v-else>

Related

How to calculate table height in watch in vue

I have a table and I give a ref to it.
<table ref="table"></table>
I want to calculate the height of this table in watcher:
watch: {
buttonClicked: {
immediate: true,
handler() {
this.$nextTick(() => {
const tableElement = this.$refs.table.$el;
const tableOffsetTop = tableElement.getBoundingClientRect().top;
});
},
},
}
But I am getting an error: Uncaught TypeError: Cannot read properties of undefined (reading '$el')
I tried ti fix it with this.$nextTick but this time I cannot calculate it right.
How can I fix it?
Try without $el:
const app = Vue.createApp({
data() {
return {
height: null
}
},
watch: {
buttonClicked: {
handler() {
this.$nextTick(() => {
const tableElement = this.$refs.table;
const tableOffsetTop = tableElement.getBoundingClientRect().top;
this.height = tableElement.getBoundingClientRect().bottom -tableElement.getBoundingClientRect().top
});
},
immediate: true,
},
}
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<table ref="table"><tr><td>table</td></tr></table>
height: {{ height }}
</div>

How can I replace element in vue.js?

Here's my code:
window.onload = (event) => {
new Vue({
el: "#test",
mounted: function() {
this.fetch();
setInterval(this.fetch, 60000);
},
data: function() {
return {
tracker: {
serverInfo: {
servername: ""
}
}
}
},
methods: {
fetch() {
fetch("https://pt.dogi.us/ParaTrackerDynamic.php?ip=pug.jactf.com&port=29071&skin=JSON")
.then(response => response.json())
.then(data => {this.tracker = data});
},
}
})
}
<script src="https://unpkg.com/vue#2.4.4/dist/vue.min.js"></script>
<div id="test">
<span style="font-weight:bold">SERVER NAME:</span> {{tracker.serverInfo.servername}}
Using vue.js how can I replace ^4Re^5fresh^11-PUG output element to
<span style="font-weight:bold">SERVER NAME:</span> <span style="color:blue">Re</span><span style="color:cyan">fresh</span><span style="color:red">1-PUG</span>
where ^4 stands for <span style="color:blue">
etc
Final result should looks like this: image
Use this regex to split the string: https://regex101.com/r/G2s23R/1
const regex = /(\^\d)([^\^]+)/gm;
// Alternative syntax using RegExp constructor
// const regex = new RegExp('(\\^\\d)([^\\^]+)', 'gm')
const str = `^4Re^5fresh^11-PUG`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
Then, I believe that you can process the remaining tasks.

How can I change selected item in qselect on page load

I use a QSelect Dropdown with some options on my page header, like the following:
<q-select
filled
v-model="model"
use-input
hide-selected
fill-input
input-debounce="0"
:options="options"
#filter="filterFn"
hint="Basic autocomplete"
style="width: 250px; padding-bottom: 32px"
emit-value
map-options
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
No results
</q-item-section>
</q-item>
</template>
</q-select>
const stringOptions = [
{label:'Google', value:'g1111111111'}, {label:'Facebook', value:'f2222222222'}, {label:'Twitter', value:'t3333333'}, {label:'Apple', value:'a44444444'}, {label:'Oracle', value:'o555555555'}
]
new Vue({
el: '#q-app',
data () {
return {
model: 'f2222222222',
options: stringOptions
}
},
methods: {
filterFn (val, update, abort) {
update(() => {
const needle = val.toLowerCase()
this.options = stringOptions.filter(v => v.label.toLowerCase().indexOf(needle) > -1)
})
}
}
})
How can I use a method to change the selected value on pageload for example from facebook to google?
I think with something like the following but cant get it working:
mounted: function () {
this.model = 'g1111111111'
},
codepen: https://codepen.io/aquadk/pen/JQbbKw
Thanks
You can use updated method, it called after the data changed and virtual dom is created for that component. Then you can update the value of the model.
const stringOptions = [
{label:'Google', value:'g1111111111'}, {label:'Facebook', value:'f2222222222'}, {label:'Twitter', value:'t3333333'}, {label:'Apple', value:'a44444444'}, {label:'Oracle', value:'o555555555'}
]
new Vue({
el: '#q-app',
data () {
return {
model: 'f2222222222',
options: stringOptions
}
},
methods: {
filterFn (val, update, abort) {
update(() => {
const needle = val.toLowerCase()
this.options = stringOptions.filter(v => v.label.toLowerCase().indexOf(needle) > -1)
})
}
},
updated(){
// Update the value of model
this.model = 'g1111111111';
}
})
The mounted should work, if it's not working the way you expect, try inside-mounted nextTick().
Here is an example with your code:
mounted () {
this.$nextTick(() => {
this.model = 'a44444444'
})
},

vuejs not setting data property from arrow function

I got this weird thing going on here:
I have this data property in vue
data() {
return {
currentLat: 'intial Lat',
currentLong: 'intial Long',
};
},
mounted() {
this.getCurrentLocation();
},
methods: {
getCurrentLocation() {
navigator.geolocation.getCurrentPosition((position) => {
this.currentLat = position.coords.latitude;
this.currentLong = position.coords.longitude;.
console.log(this.currentLat); this prints 41.2111
});
console.log(this.currentLat); this prints 'intial Lat'
},
},
this.currentLat not set in the mount
I dont understand what's happing here! it's so weird!
Here is an example of converting to a promise and using async/await:
async getCurrentLocation() {
const position = await new Promise(resolve => {
navigator.geolocation.getCurrentPosition(position => resolve(position))
});
this.currentLat = position.coords.latitude;
this.currentLong = position.coords.longitude;
console.log(this.currentLat); // shouldn't print initial value
},
Your code is valid, the callback arrow function is asynchronous (it's not executed immediately) and the call of console.log(this.currentLat); is synchronous which makes it to be executed before the callback context, the property is properly if you use it inside the template it will work fine
Set the values in a callback as follows:
<template>
<div id="app">{{ currentLat }} - {{ currentLong }}</div>
</template>
<script>
export default {
data() {
return {
currentLat: "intial Lat",
currentLong: "intial Long",
};
},
mounted() {
this.getCurrentLocation();
},
methods: {
getCurrentLocation() {
navigator.geolocation.getCurrentPosition(this.setCoordinates);
},
setCoordinates(position) {
this.currentLat = position.coords.latitude;
this.currentLong = position.coords.longitude;
},
},
};
</script>

vue-pdf doesn't refresh on src change

I'm using the latest vue-pdf package to display pdf files in my app. I built this component, PdfViewer:
<template>
<div class="fill-height pdf-container">
<template v-if="src && numberOfPages">
<pdf
v-for="page in numberOfPages"
:key="`${fileName}-${page}`"
:src="src"
:page="page"
/>
</template>
</div>
</template>
import { mapGetters } from 'vuex'
import pdf from 'vue-pdf'
export default {
props: {
fileName: {
type: String,
required: true
}
},
components: {
pdf
},
data() {
return {
src: null,
numberOfPages: 0
}
},
computed: {
...mapGetters({
getAttachments: 'questions/getAttachments'
})
},
methods: {
init() {
if (this.fileName) {
let url = this.getAttachments[this.fileName]
let loadingTask = pdf.createLoadingTask(url)
this.src = loadingTask
this.src.promise.then(pdf => {
this.numberOfPages = pdf.numPages
})
}
},
},
watch: {
fileName() {
this.init()
}
},
beforeMount() {
this.init()
}
}
Basically I'm receiving a fileName as a prop, then look for its URL in the object I receive in getAttachments getter. The file names are in different list component.
It works fine on the first run and the first file is loaded and displayed successfully. But once clicked on another file name - nothing being displayed. I do receive the file name prop and it does find the URL, but the file doesn't display. Even when I click on the file that has already been displayed - now it doesn't.
I thought maybe it has something to do with src and numberOfPages property, so I tried to reset them before loading the file:
init() {
if (this.fileName) {
this.src = null
this.numberOfPages = 0
let url = this.getAttachments[this.fileName]
let loadingTask = pdf.createLoadingTask(url)
this.src = loadingTask
this.src.promise.then(pdf => {
this.numberOfPages = pdf.numPages
})
}
}
Alas, same result. And in the console I see the following warning from pdf.worker.js: Warning: TT: invalid function id: 9
Have no idea what it means.
Any help, please?
EDIT
I tried to do that with async/await and forceUpdate:
async init() {
if (this.fileName) {
this.src = null
this.numberOfPages = 0
let url = this.getAttachments[this.fileName]
let loadingTask = await pdf.createLoadingTask(url)
await loadingTask.promise.then(pdf => {
this.src = url
this.numberOfPages = pdf.numPages
})
this.$forceUpdate()
}
}
That also didn't help. But I found out that once I change the passed fileName, the code does go to the init() method, but for some reason it skips the loadingTask.promise.then part, doesn't go in. I have to idea why.
Well, apparently there's some issue with vue-pdf library. Eventually I solved it by setting timeout when assigning fileName prop and re-rendering the component:
<PdfViewer v-if="selectedFileName" :fileName="selectedFileName" />
onFileNameSelected(fileName) {
this.selectedFileName = null
setTimeout(() => {
this.selectedFileName = fileName
}, 0)
}
And then in the PdfViewer component it's just:
created() {
this.src = pdf.createLoadingTask(this.getAttachments[this.fileName])
},
mounted() {
this.src.promise.then(pdf => {
this.numberOfPages = pdf.numPages
})
}
That did the trick for me, though feels kinda hacky.