How to pass array index in image src in Vuejs v-img? - javascript

Hey im trying to iterate through an array of urls to feed it inside of my src attribute. I'm not sure about the correct syntax to use. Can you help me?
I have my array called DataArray made of images url, and i want to insert inside of v-img in v-row. i tried this :src=DataArray[n] but it's not the correct way.
<template>
<v-container v-if="Dataloaded" class="dark">
<v-row no-gutters>
<template v-for="n in 6">
<v-col :key="n">
<v-card dark class="mx-auto" max-width="344">
<v-img :src=DataArray[n] height="200px"></v-img>
<v-card-title>Title</v-card-title>
<v-card-subtitle>Anime-Descriptions</v-card-subtitle>
<v-card-actions>
<v-btn text>View</v-btn>
<v-btn color="purple" text>Explore</v-btn>
<v-spacer></v-spacer>
<v-btn icon #click="show = !show">
<v-icon>{{ show ? 'mdi-chevron-up' : 'mdi-chevron-down' }}</v-icon>
</v-btn>
</v-card-actions>
<v-expand-transition>
<div v-show="show">
<v-divider></v-divider>
<v-card-text>I'm a thing. But, like most politicians, he promised more than he could deliver. You won't have time for sleeping, soldier, not with all the bed making you'll be doing. Then we'll go with that data file! Hey, you add a one and two zeros to that or we walk! You're going to do his laundry? I've got to find a way to escape.</v-card-text>
</div>
</v-expand-transition>
</v-card>
<!-- spacing -->
<br :key="1" />
<br :key="2" />
</v-col>
<v-responsive v-if="n === 3" :key="`width-${n}`" width="100%"></v-responsive>
</template>
</v-row>
</v-container>
</template>
<script>
import db from "#/Firebase/firebaseInit";
export default {
name: "Grid",
data() {
return {
DataArray: [],
Dataloaded: false,
show: false
};
},
created() {
let ArtData = db.collection("artworks").doc("yWnmwHTxMhvobLi21FNw");
ArtData.get()
.then(doc => {
if (doc.exists) {
// This variable contains all the necessary artworks for display
let DataArray = doc.data().Array;
console.log("Document data!:", DataArray);
this.Dataloaded = true;
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
.catch(function(error) {
console.log("Error getting document:", error);
});
}
};
</script>

Change this:
let DataArray = doc.data().Array;
to:
this.DataArray = doc.data().Array;
And use this to show the image:
<v-img :src="DataArray[n-1]" height="50px"></v-img>
n-1 because the v-for you're using is 1-based.

Related

How to submit form to array and clear inputs in vue

I have a vue form inside a dialog. Where the user can select a date and multplie starting times and ending times. So far I can save one object consisting of one date and multiple times. But when I want to add another object it takes the new date but changes the time values for every object.
for example if I add first an object with 05.09.2021 start:15:00 end: 16:00 and then add another object with date: 06.09.2021 start: 16:00 end: 17:00. The start and end is changed to the latest value of all objects, but I want each of them to be individually. I tried submitting a form, but sadly I could not make it work because it is reloading the page which I do not want, if i use .prevent on submit my error with time changing for every object still consists. Could someone take a look at my code and point me my mistake out`?
HTML:
<v-row>
<v-col cols="12" sm="12">
<v-menu
ref="menu3"
v-model="menu3"
:close-on-content-click="false"
:return-value.sync="dates"
transition="scale-transition"
offset-y
min-width="auto"
>
<template v-slot:activator="{ on, attrs }" >
<v-text-field
v-model="dates"
label="Picker in menu"
prepend-icon="mdi-calendar"
readonly
v-bind="attrs"
v-on="on"
></v-text-field>
</template>
<v-date-picker
v-model="dates"
no-title
scrollable
>
<v-spacer/>
<v-btn
text
color="primary"
#click="menu3 = false"
>
Cancel
</v-btn>
<v-btn
text
color="primary"
#click="$refs.menu3.save(dates) "
v-on:click=" menu3 = false"
>
OK
</v-btn>
</v-date-picker>
</v-menu>
<v-btn v-on:click="addTimeFields()">Add Time</v-btn>
</v-col>
</v-row>
<v-row v-for="(find, index) in selectedTime" >
<v-col
cols="6"
sm="6">
<v-text-field
v-model="find.startTime"
label="Starttime"
type="time"
></v-text-field>
</v-col>
<v-col
cols="6"
sm="6">
<v-text-field
v-model="find.endTime"
label="Untiltime"
type="time"></v-text-field>
</v-col>
</v-row>
</form>
Javascript:
<script>
import MeetingsTableComponent from "#/components/MeetingsTableComponent";
import DatePickerComponent from "#/components/DatePickerComponent";
export default {
name: "NextMeetingCardComponent",
data: () => ({
selectedTime: [],
dates: new Date().toISOString().substr(0,10),
datesFinal: [],
dialog: false,
menu: false,
modal: false,
menu2: false,
menu3: false
}),
methods:{
addTimeFields(){
this.selectedTime.push({
startTime:"",
endTime: "",
})
},
saveDateAndTIme(e){
this.datesFinal.push({
date: this.dates,
times : [this.selectedTime]
}
)
this.$refs.form.submit()
},
clearArrays(){
while (this.selectedTime.length){
this.selectedTime.pop()
}
}
}
};
</script>
I tried clearing the selectedTimes array which is pushed to datesFinal after pushing it but then every value is deleted.
I think there's an error in saveDateAndTIme(): times contains a nested array of the this.selectedTime array, but that should be unnested (i.e., set times to this.selectedTime itself).
After pushing this.selectedTime into datesFinal, you could clear the form by setting this.selectedTime to an empty array.
export default {
methods: {
saveDateAndTIme(e) {
this.datesFinal.push({
date: this.dates,
times: this.selectedTime, 👈
})
this.selectedTime = [] 👈
},
}
}
demo

how to pass variable between to vue file?

how to pass variable between to vue file ?
Hello, this is my file SendCode.vue has variable NewEmail which I want to use it in another file changePass.vue .
Is there anyway to sole this ?
Can someone help me ? Thanks
<template>
<v-app id="inspire">
<v-content>
<v-container class="fill-height" fluid>
<v-row align="center" justify="center">
<v-col cols="12" sm="8" md="4">
<v-card class="elevation-12">
<v-toolbar color="#ff8c00">
<v-toolbar-title>Glömt lösenord!</v-toolbar-title>
</v-toolbar>
<v-card-text>
Skrive ditt email.
<v-form>
<v-text-field v-model="email"
:error-messages="emailErrors"
label="E-mail"
required
#input="$v.email.$touch()"
#blur="$v.email.$touch()"></v-text-field>
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn #click="getCode" color="primary">Skicka koden</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</v-content>
</v-app>
</template>
<script>
import axios from 'axios'
import router from '#/router.js'
import { validationMixin } from 'vuelidate'
import { required, email } from 'vuelidate/lib/validators'
export default {
mixins: [validationMixin],
validations: {
email: { required, email },
checkbox: {
checked(val) {
return val
}
}
},
props: {
source: String,
},
data: () => ({
email: ""
}),
methods: {
getCode: async function() {
let obj = {
"email": this.email,
};
let NewEmail = this.email;
let response = await this.$store.dispatch("getCode", obj);
//console.log(email)
//console.log(this.email)
if (response.status == 200) {
setTimeout(function() {
router.push({
path: 'ChangePass'
});
}, 500);
}
}
}
}
</script>
I want to use/pass variable NewEmail in this file from SendCode.vue file
I am new in vue and javascript so I do not know how to do this.
<template>
<v-app id="inspire">
<v-content>
<v-container class="fill-height" fluid>
<v-row align="center" justify="center">
<v-col cols="12" sm="8" md="4">
<v-card class="elevation-12">
<v-toolbar color="#ff8c00">
<v-toolbar-title>ÄNDRA LÖSENORDET</v-toolbar-title>
</v-toolbar>
<v-card-text>
<v-form>
<v-text-field :error="pass1Error" label="Koden" v-model="code1" type="password" />
<v-text-field :error="pass2Error" label="Lössenord" v-model="newPassword" type="password" />
<v-text-field :error="pass1Error" label="Samma Lössenord" v-model="rePassword" type="password" />
</v-form>
</v-card-text>
<v-alert v-if="passError" type="error">
password are not same
</v-alert>
<v-alert v-if="passwordChanged" type="success">
Password has been updated!
</v-alert>
<v-card-actions>
<v-spacer />
<v-btn #click="change" color="primary">Ändra</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</v-content>
</v-app>
</template>
<script>
import axios from 'axios'
import SendCode from "#/views/SendCode.vue";
import { validationMixin } from 'vuelidate'
import { required, email } from 'vuelidate/lib/validators'
export default {
mixins: [validationMixin],
validations: {
email: { required, email },
checkbox: {
checked(val) {
return val
}
}
},
props: {
source: String,
},
data: () => ({
code1: "",
newPassword: "",
rePassword: ""
}),
methods: {
change: async function() {
let obj = {
"code1": this.code1,
"newPassword": this.newPassword,
"rePassword": this.rePassword,
};
console.log(obj)
let response = await this.$store.dispatch("changePass", obj);
}
}
}
</script>
We recommend that you use Vuex (State management) for easy transfer and management of data through pages
Documentation:
https://vuex.vuejs.org/
If its only a variable with some value in it you can store it in localstorage i assume.
So in your function where you have the data you want to pass add:
localStorage.setItem('email', variable).
This works as a key value pair where email is the key and the variable is the data you want to access.
Then where you want to access the data you can use:
localStorage.getItem('email')
You probably don't want to do what you're trying to do, but would be better off with state management (vuex/pinia/genericVueStore), or, if you want to pass the data between components in the same app (same project), then the main method is $emits and $props. Check Vue documentation to see if that is what you want, which it probably is.
Nevertheless, within a Vue project, you can generally use Node/ES methods. So, the following would be fine, and would fit into the "composables" category if they weren't ".vue" files.
>> file1.vue
<script setup>
const oneData = "this_text"
export {oneData}
...
>> file2.vue
import {oneData} from "#/file1.vue"
console.log(oneData}
This would be an anti-pattern. Just follow the documentation for the standard things people try to accomplish.

Computing props within a v-for loop

I have an array of object - some of which need to have a property tweaked depending on their value. In a v-for loop, how do I ammend a value, is this what computed is for?
I have tried creating and accessing a computed value but I suspect I am misunderstanding the order of events here.
<template>
<v-container grid-list-md>
<v-layout row wrap>
<v-flex xs6 md3 v-for="item in items" :key="item.da_id">
<v-card>
<v-img
:src="item.imgUrl"
aspect-ratio="2.75"
></v-img>
<v-card-title primary-title>
<div>
<h3 class="headline mb-0">{{item.title}}</h3>
</div>
</v-card-title>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import axios from 'axios'
export default {
data() {
imgUrl: {
return ''
}
},
async asyncData ({ params }) {
let {data} = await axios.get(`http://XXX.XXX.XXX.192:8080/api/collection/${params.id}`)
return { items: data }
},
computed: {
imgUrl(item) {
console.log(this.items.map(item))
return 'https://aijxxppmen.cloudimg.io/crop/500x500/tjpg/https://dartmoorpublic.s3-eu-west-1.amazonaws.com/' + this.items.file_id
}
}
}
</script>
I am expecting each v-card :src value to be different and based on the computed function I have created. I am getting undefined.
You are not looking for a computed property. Computed properties are properties of the Vue instance, not of the elements in your items array. You will want to use a method instead:
<template>
<v-container grid-list-md>
<v-layout row wrap>
<v-flex xs6 md3 v-for="item in items" :key="item.da_id">
<v-card>
<v-img
:src="imgUrl(item)"
aspect-ratio="2.75"
></v-img>
<v-card-title primary-title>
<div>
<h3 class="headline mb-0">{{item.title}}</h3>
</div>
</v-card-title>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
import axios from 'axios'
export default {
data() {
imgUrl: {
return ''
}
},
async asyncData ({ params }) {
let {data} = await axios.get(`http://XXX.XXX.XXX.192:8080/api/collection/${params.id}`)
return { items: data }
},
methods: {
imgUrl(item) {
console.log(item)
return 'https://aijxxppmen.cloudimg.io/crop/500x500/tjpg/https://dartmoorpublic.s3-eu-west-1.amazonaws.com/' + item.file_id
}
}
}

vuetify autocomplete preload

i'm learning vuetify framework, i managed to use most of the components but i have a problem with autocomplete component.
Using it from scratch works fine, bug if i try to set value during creation it doesn't work at all.
I tried to extend one of the vuetify example but without success.
i would like to load first value from the API during creation but it stays empty.
Thanks for your help.
new Vue({
el: '#app',
data: () => ({
descriptionLimit: 60,
entries: [],
isLoading: false,
model: null,
search: "Cats"
}),
created :function() {
model={"API":"Cats","Description":"Pictures of cats from Tumblr","Auth":"","HTTPS":true,"Cors":"unknown","Link":"https://thecatapi.com/docs.html","Category":"Animals"},
search="Cats"
},
computed: {
fields () {
if (!this.model) return []
return Object.keys(this.model).map(key => {
return {
key: key,
value: this.model[key] || 'n/a'
}
})
},
items () {
return this.entries.map(entry => {
const Description = entry.Description.length > this.descriptionLimit
? entry.Description.slice(0, this.descriptionLimit) + '...'
: entry.Description
return Object.assign({}, entry, { Description })
})
}
},
watch: {
search (val) {
// Items have already been loaded
if (this.items.length > 0) return
this.isLoading = true
console.log("loadgin data")
// Lazily load input items
axios.get('https://api.publicapis.org/entries')
.then(res => {
const { count, entries } = res.data
this.count = count
this.entries = entries
})
.catch(err => {
console.log(err)
})
.finally(() => (this.isLoading = false))
}
}
})
<div id="app">
<v-app id="inspire">
<v-card
color="red lighten-2"
dark
>
<v-card-title class="headline red lighten-3">
Search for Public APIs
</v-card-title>
<v-card-text>
Explore hundreds of free API's ready for consumption! For more information visit
<a
class="grey--text text--lighten-3"
href="https://github.com/toddmotto/public-apis"
target="_blank"
>the Github repository</a>.
</v-card-text>
<v-card-text>
<v-autocomplete
v-model="model"
:items="items"
:loading="isLoading"
:search-input.sync="search"
color="white"
hide-no-data
hide-selected
item-text="Description"
item-value="API"
label="Public APIs"
placeholder="Start typing to Search"
prepend-icon="mdi-database-search"
return-object
></v-autocomplete>
</v-card-text>
<v-divider></v-divider>
<v-expand-transition>
<v-list v-if="model" class="red lighten-3">
<v-list-tile
v-for="(field, i) in fields"
:key="i"
>
<v-list-tile-content>
<v-list-tile-title v-text="field.value"></v-list-tile-title>
<v-list-tile-sub-title v-text="field.key"></v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-expand-transition>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
:disabled="!model"
color="grey darken-3"
#click="model = null"
>
Clear
<v-icon right>mdi-close-circle</v-icon>
</v-btn>
</v-card-actions>
</v-card>
</v-app>
</div>
If this is the code you are trying to use then you are missing a ',' at the end of the "model".
created :function() {
model={...}, <----
search="Cats"
},
blalan05 on the discrod channel just give me the reply : my created function was garbled.
new Vue({
el: '#app',
data: () => ({
descriptionLimit: 60,
entries: [],
isLoading: false,
model: null,
search: "Cats"
}),
created () {
this.model = {"API":"Cats","Description":"Pictures of cats from Tumblr","Auth":"","HTTPS":true,"Cors":"unknown","Link":"https://thecatapi.com/docs.html","Category":"Animals"},
this.search = "Cats"
},
computed: {
fields () {
if (!this.model) return []
return Object.keys(this.model).map(key => {
return {
key: key,
value: this.model[key] || 'n/a'
}
})
},
items () {
return this.entries.map(entry => {
const Description = entry.Description.length > this.descriptionLimit
? entry.Description.slice(0, this.descriptionLimit) + '...'
: entry.Description
return Object.assign({}, entry, { Description })
})
}
},
watch: {
search (val) {
// Items have already been loaded
if (this.items.length > 0) return
this.isLoading = true
console.log("loadgin data")
// Lazily load input items
axios.get('https://api.publicapis.org/entries')
.then(res => {
const { count, entries } = res.data
this.count = count
this.entries = entries
})
.catch(err => {
console.log(err)
})
.finally(() => (this.isLoading = false))
}
}
})
<div id="app">
<v-app id="inspire">
<v-card
color="red lighten-2"
dark
>
<v-card-title class="headline red lighten-3">
Search for Public APIssss
</v-card-title>
<v-card-text>
Explore hundreds of free API's ready for consumption! For more information visit
<a
class="grey--text text--lighten-3"
href="https://github.com/toddmotto/public-apis"
target="_blank"
>the Github repositoryyy</a>.
</v-card-text>
<v-card-text>
<v-autocomplete
v-model="model"
:items="items"
:loading="isLoading"
:search-input.sync="search"
color="white"
hide-no-data
hide-selected
item-text="Description"
item-value="API"
label="Public APIs"
placeholder="Start typing to Search"
prepend-icon="mdi-database-search"
return-object
></v-autocomplete>
</v-card-text>
<v-divider></v-divider>
<v-expand-transition>
<v-list v-if="model" class="red lighten-3">
<v-list-tile
v-for="(field, i) in fields"
:key="i"
>
<v-list-tile-content>
<v-list-tile-title v-text="field.value"></v-list-tile-title>
<v-list-tile-sub-title v-text="field.key"></v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-expand-transition>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
:disabled="!model"
color="grey darken-3"
#click="model = null"
>
Clear
<v-icon right>mdi-close-circle</v-icon>
</v-btn>
</v-card-actions>
</v-card>
</v-app>
</div>

Array filter not working on page refresh while using vue-router

I have this method (below), which works perfectly when I'm directed from a <router-link>.
selectedSpaceObj() {
if (!this.selectedSpace) {
return {};
} else {
return this.spaces.filter(aSpace => aSpace.id === this.selectedSpace);
}
}
However on refreshing the page, or going to the link directly it doesn't work. I can confirm that this.selectedSpace has a value even after the refresh. If I get routed to this page with a param of 1, and have the url myspaces/1, I store this value in selectedSpace, however on refresh I get an empty array (or some sort of weird array). But it shouldn't be? Anyone know how to fix this error?
Here is the rest of my code:
routes.js contains these two paths:
{
path: '/myspaces',
name: 'myspaces',
component: MySpaces
},
{
path: '/myspaces/:spaceID',
name: 'returnToSpaces',
component: MySpaces,
props: true
}
The concept behind it is that I pass spaceID via a <router-link>, from 1 page to another. This works. The spaceID is passed on correctly.
Room.vue - has a router-link to MySpaces.vue
<router-link :to="{ name: 'returnToSpaces', params: { spaceID: spaceID } }">
<v-btn>
<h3> go back </h3>
</v-btn>
</router-link>
When I'm on the room.vue and I click on the button, it redirects me to the myspaces.vue as the link myspaces/1 correctly with a spaceID. However If I type myspaces/1 manually instead of being redirected, it doesn't work. It gives me the error: Cannot read property 'rooms' of undefined. This prop is linked to the spaceID which, so most likely when I refresh it, it doesn't link the /1 to the spaceID parameter?
myspaces.vue
<template>
<v-container>
<v-layout>
<!-- My spaces -->
<v-flex md8 xs12>
<v-layout row wrap>
<!-- The rooms, allRoomsObj returns all rooms in the space with the id of selectedSpace. -->
<v-flex v-for="room in allRoomsObj"
:key="room.id"
xs12
sm6
md6
lg6
:class="{'roomDesktop': !$vuetify.breakpoint.xs, 'roomMobile': $vuetify.breakpoint.xs}"
>
<!-- A room -->
<v-card class="card-round">
<!-- Image -->
<v-carousel :cycle="false" hide-delimiters :hide-controls="room.images.length <= 1">
<!--:hide-controls="images.length <= 1"-->
<v-carousel-item v-for="image in room.images" :src="image.src" :key="image.id"></v-carousel-item>
</v-carousel>
<!-- Information -->
<v-card-text primary-title>
<v-layout>
<v-flex xs11>
<!-- MISSING INFORMATION IN STORE -->
<h4 class="roomType"> <router-link :to="{ name: 'room', params: { spaceID: selectedSpaceObj[0].id, roomID: room.id } }">{{ room.type }}</router-link> </h4>
<h2> {{ room.name }} </h2>
</v-flex>
<v-flex xs1 hidden-sm-and-down>
<v-btn #click="selectedRoom = room.id"
:flat="selectedRoom !== room.id"
:outline="selectedRoom !== room.id"
fab
class="selectRoomBtn"
depressed
>
</v-btn>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</v-flex>
<!-- Sidebar -->
<v-flex hidden-sm-and-down sm4 lg4 class="sidebarSticky">
<v-layout row wrap>
<!--1 room details, selectedRoomObj returns 1 room with id of selectedRoom, that is in the space with id selectedSpace.-->
<v-flex v-for="room in selectedRoomObj" :key="room.id">
<v-card class="card-round">
<!-- Show only 1 image -->
<v-card-media v-for="image in room.images.slice(0,1)" :src="image.src" height="200px" :key="image.id">
</v-card-media>
<v-card-text>
<!-- Side bar - room name -->
<h2 class="sidebarRoomName"> {{ room.name }} </h2>
<!-- description -->
<p> {{ room.description }} </p>
<!-- overview button-->
<p> <router-link :to="{ name: 'room', params: { spaceID: selectedSpace, roomID: selectedRoom } }">room overview..</router-link></p>
<!-- styles/pins/moodboard -->
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-container> <!-- End of MAIN CONTENT-->
</template>
<script>
import { mapState } from 'vuex';
export default {
name: "myspaces",
props: [
'spaceID'
],
data() {
return {
filterMaxLength: 3,
selectedSpace: 0,
selectedRoom: 0
}
},
created() {
// Default selected space (first in json)
this.selectedSpace = this.spaces[0].id;
// console.log("spaces " + this.spaces[0].id)
if (this.spaceID != null) {
this.selectedSpace = this.spaceID;
}
// Default selected room (first in json)
this.selectedRoom = this.spaces[0].rooms[0].id;
// If spaceID is received, change the room to the first room in that space.
if (this.spaceID != null) {
var backToSpace = this.spaces.filter(aSpace => aSpace.id == this.spaceID)
this.selectedRoom = backToSpace[0].rooms[0].id
}
},
computed: {
// Get 'spaces' from store.
...mapState([
'spaces'
]),
// Grab all the rooms in the selected space.
allRoomsObj() {
if (!this.selectedSpaceObj) {
return {};
} else {
return this.selectedSpaceObj[0].rooms;
}
},
// Grab the space that with the id that equals to the selectedSpace.
selectedSpaceObj() {
if (!this.selectedSpace) {
return {};
} else {
return this.spaces.filter(aSpace => aSpace.id === this.selectedSpace);
}
},
// Grab the room in the selected space, with the room id that equals to selectedRoom.
selectedRoomObj() {
if (!this.selectedSpaceObj) {
return {};
} else {
return this.selectedSpaceObj[0].rooms.filter(aRoom => aRoom.id === this.selectedRoom);
}
}
}
}
</script>
I think the problem might be the type strict comparison inside this code (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators) - "puelo"
change this:
this.spaces.filter(aSpace => aSpace.id === this.selectedSpace)
to
this.spaces.filter(aSpace => aSpace.id == this.selectedSpace)

Categories