I have a getVueItems mehod that return products:
getVueItems: function(page){
axios.get('./api/home/product').then(response => {
this.items = response.data;
});
},
<div v-for="item in items" :key="item.id">
.
.
.
<a #click="AddCart()"></a>
</div>
as you see i have a another method that name is AddCart, this method is independent and must running a unique url to add the item to cart:
AddCart() {
axios.get( `./add-to-card/1`)
.then((response) => {
this.$store.dispatch('CartDetail')
});
},
in AddCart() axios url i need to get the id of product,how can i do this?
You have access to item in the scope of your v-for tag/block. Just do <a #click="AddCart(item.id)"></a>, and receive the argument with AddCart(id) {}
Related
Having the following snippet trying to fill an array of object with async alpine call but I can not get any result. Hier is what I try.
HTML:
<div x-init="experts.retrieveList" x-data="experts.list">
<ul>
<template x-for="item in experts.list" :key="item">
<li>
<div x-text="await item.address" ></div>
</li>
</template>
</ul>
</div>
external JS file
window.experts = {
apiUrl: 'http://bdb.local:8991/api/',
data: [],
list: [],
expertsForm: null,
retrieveList: () => {
const membersUrl = `${experts.apiUrl}members?include=user,association,affiliate`;
experts.apiCalls(membersUrl)
},
filterByParams: () => {
},
apiCalls: async (url) => {
let response = await fetch(url);
experts.list = await response.json()
return experts.list;
},
}
What is wrong in this case?
There are a few errors in this code:
You cannot use just a part of an Alpine.js component in the x-data="experts.list". If you don't define data variables directly in x-data, then it must be a real component that returns data and methods.
You cannot use an object as the key. It must be a string or number, like item.id or something like this.
The x-text="await item.address" seems incorrect. item.address should be a string, that has been already downloaded from the API.
In the component you need to use the this. prefix to access properties and methods.
Assuming your API returns the correct data format, something like this should work:
<div x-data="experts">
<ul>
<template x-for="item in list" :key="item.id">
<li>
<div x-text="item.address"></div>
</li>
</template>
</ul>
</div>
And the component in an external file:
const experts = {
apiUrl: 'http://bdb.local:8991/api/',
data: [],
list: [],
expertsForm: null,
init() {
const membersUrl = `${experts.apiUrl}members?include=user,association,affiliate`
this.apiCalls(membersUrl)
},
filterByParams() {
},
async apiCalls(url) {
let response = await fetch(url)
this.list = await response.json()
},
}
The init() method is executed automatically by Alpine.js.
Here is my scenario, i am trying to use the id coming from one API response in another API :
Below is Component.vue:
<template>
<div class="Contents">
<div class="vx-col" v-for="idea in ideas" v-bind:key="idea.id">
<vx-card>
...
<div>
{{idea.name}} of {{idea.id}}
</div>
<div v-if="sum">
{{sum.total}}
</div>
...
</vx-card>
</div>
</div>
</template>
<script>
...
async created () {
await this.$http.get('/ideas')
.then((response) => { this.ideas = response.data })
.catch((error) => { console.log(error) })
},
methods: {
getSumOfIdeas(id){
this.$http.get('/sum_of_ideas/'+ id +'/everything')
.then((response) => { this.sum = response.data })
.catch((error) => {console.log(error)})
}
},
mounted (){
this.getSumOfIdeas(this.ideas.id) //Here i am trying to give that id coming from the /ideas
}
</script>
Here is what console.log(response.data) gives in /ideas:
Don't know where i am going wrong, currently in my console i get an error as :
/sum_of_ideas/undefined/everything // so here id coming from the /ideas should have been rendered.
To make it clear i have used an example of {{idea.id}} and this displays just the number each time it loops.
Please help me in this, i want to use the response coming from the /ideas ie id in another response here it is /sum-of-ideas.
When you are calling this.getSumOfIdeas(this.ideas.id) you are trying to access id of ideas which does not exist. Either use something like this.getSumOfIdeas(this.ideas[0].id) to access id of the first object or use a loop to iterate over the ideas and call this.getSumOfIdeas(this.ideas.id).
this.ideas.forEach(idea => this.getSumOfIdeas(idea.id))
promise and async await both are used, use any one only.
execute getSumOfIdeas after assigning this.ideas which is in created hook
<template>
<div class="Contents">
<div class="vx-col" v-for="idea in ideas" v-bind:key="idea.id">
...
<div>
{{idea.name}} of {{idea.id}}
</div>
<div v-if="sum">
{{sum.total}}
</div>
...
</div>
</div>
</template>
<script>
...
created () { // remove async and await
this.$http.get('/ideas')
.then((response) => {
this.ideas = response.data;
this.getSumOfIdeas(this.ideas.id); // Do this here after assigning ideas
})
.catch((error) => { console.log(error) })
},
methods: {
getSumOfIdeas(id){
this.$http.get('/sum_of_ideas/'+ id +'/everything')
.then((response) => { this.sum = response.data })
.catch((error) => {console.log(error)})
}
},
mounted (){
// this.getSumOfIdeas(this.ideas.id) // move to created
}
</script>
My template has following:
<ul id="example-1">
<li v-for="item in getMenus" :key="item.id">
{{ item.name }}
</li>
</ul>
methods:{
async getMenus() {
this.$axios.setHeader('Content-Type', 'application/json', ['get'])
this.$axios.setHeader(
'Authorization',
'Bearer ' + this.$store.state.auth.Token
)
const roleId = this.$store.state.auth.role.roleId
const url = `/role/${roleId}/menu`
let data = ''
// eslint-disable-next-line vue/no-async-in-computed-properties
const pal = await this.$axios
.$get(url, JSON.stringify(roleId))
.then(function(resp) {
data = resp.data
})
if (pal) {
// eslint-disable-next-line no-console
console.log('hi')
}
return data
}
}
}
Above mentioned is my code. I checked my api its returing data. If i put directly my data as harcoded value then it works, if I use api then it doesnot work. I looke dinto console also that is also clear. I am new to vue. Any help will be highly appreciated.
You can't use async methods in v-for. Define an array in data section of a component and write results in the array at the end of getMenus function. You should call getMenus at some place in your code (for instance in mounted hook):
<li v-for="item in menuList" :key="item.id">
...
// in a component code
data: {
return {
menuList: []
}
},
mounted () {
// if you don't have any initialization after this call you can call it without await
getMenus()
},
methods:{
async getMenus() {
...
// getting results
const { data: menuList } = await this.$axios
.$get(url, JSON.stringify(roleId))
this.menuList = menuList
}
This happens because inside async getMenus method you are returning data before it is even assigned a value. A better way to resolve this issue would be to set a variable in data options like:
data() {
return {
loading: false,
items: [] // This will hold all the getMenus() data
}
},
and inside getMenus update items array like:
created() {
this.getMenus();
},
methods: {
async getMenus() {
this.loading = true;
// All other logic here...
this.$axios.$get(url, JSON.stringify(roleId))
.then(resp => {
this.loading = false;
this.items = resp.data; // Set the response data here...
})
.catch(error => {
this.loading = false;
console.log(error);
})
}
}
and then update your template like:
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
In case, your async method is going to take some time to finish you can show a loading text or icon so that user know that at least something is happening instead of looking at a blank screen like:
<template v-if="loading">
Loading...
</template>
<template v-else>
<ul id="example-1">
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</ul>
</template>
Can i get properties from template before send request to server about the data?
Here's my template:
<box-component inline-template>
<div>
<div class="loading" v-if="Loading"> Loading ... </div>
<div v-if="Result">
<ul>
<li> {{ Result.FirstProp }} </li>
<li> {{ Result.FourthProp }} </li>
</ul>
</div>
</div>
And this is my component:
let BoxComponent = {
data() {
return {
Result: null,
Loading: true
};
},
created: function () {
this.Update();
},
methods: {
Update: function () {
this.Loading = true;
axios.post("#SERVER_URL#")
.then(response => {
this.Loading = false;
this.Result = response.data;
});
}
}
}
Vue.component('box-component', BoxComponent);
It's works fine! The problem is the server response contain much more data. Server response:
{
"FirstProp": "first",
"SecondProp": "second"
...
"HundredthProp": "hudredth"
}
I can't modify the response (other project use this too). But if i am able to send property list from the template (which are in this case FirstProp and FourthProp) the server side give me the filtered response which contains only these properties becouse the optimal response look like this:
{
"FirstProp": "first",
"FourthProp": "fourth"
}
So, the question is: how can i do that?
Can i find it in the Vue object?
I can load template as a string variable, but i want to avoid regex hack.
Update:
In this case, BoxTemplate call server side without "filters"
This is the optimal case, when js get the variables, that the template use, and call with them the server side. In this case, in the response there are only that variables, what template really use
I don't know how is set up your back-end but you can have additional property within your data:
data() {
return {
listOfProperty: [
'FirstProp',
'FourthProp',
],
...
And use list of it to send data to server.
Hi I am pretty new to VueJS and have started working on a very simple API request. I have an object that looks like this:
posts: [
text: "String",
choices: {"1":"Yes","2":"No"}
]
Coming from angular, this seems very straightforward. I would just use a filter to convert choices to an object and loop over it. However, I ran into a problem. When I attempt to use the filter 'log' or 'json' in the v-for, they don't work.
<template>
<div>
<li v-for="(post,index) in posts | log">
<ul>
{{ post.text | log }}
{{ post.choices | json }}
<li v-for="(value,key) in post.choices | json">
{{value}} {{key}}
</li>
</ul>
</li>
</div>
</template>
<script>
import {HTTP} from './main';
export default {
filters: {
json: function (value) {
return JSON.parse(value)
},
log: function (value) {
console.log(value)
}
},
props: [
'apiKey'
],
data: () => ({
posts: [],
post: [],
errors: []
}),
created() {
HTTP.get('questions', { headers: { 'Api-Key': this.apiKey} })
.then(response => {
this.posts = response.data
})
.catch(e => {
this.errors.push(e)
})
}
}
</script>
Then no data shows up, however they work fine in the mustache template. Any thoughts on how I can accomplish this?
tl;dr
works:
{{ post.choices | json }}
does not work:
<li v-for="(value,key) in post.choices | json">
Any work around? I can't use computed properties because this is a "sub-object" of an array and computed properties don't work that way, unless I am mistaken?
You cannot add a filter to a v-for directive.
Just parse the data before setting the posts data property:
HTTP.get('questions', { headers: { 'Api-Key': this.apiKey} })
.then(response => {
let posts = response.data;
post.forEach(p => p.choices = JSON.parse(p.choices));
this.posts = posts;
})
I don't see why you need to use JSON.parse, since the choices key refers to a valid JS object. Unless you have made a mistake, and that the choices key refers to a string.
Anyway, if you want to parse post.choice into a valid JS object, you can simply pass it into a custom function which returns the parsed JSON to v-for, for example:
<li v-for="(value,key) in postChoicesJson(post.choice)">
{{value}} {{key}}
</li>
And then declare a method for that:
postChoicesJson: function(obj) {
return JSON.parse(obj);
}
Note: Your DOM is invalid, because <li> elements must be a direct child of a <ul> or an <ol> element.