Filter data coming from API with Nuxt - vue.js

Im using slick slider in Nuxt im getting the images from an API with Axios
The API look like this :
"images_selection": [
{
title: 'Global Landing',
slug: 'global-landing-1',
id: 113,
images: [
{
title: '',
description: '',
file_extension: 'jpeg',
position: 0,
url: 'https://####images',
type: 0,
link: '',
id: 3603,
video_link: '',
},
],
},
{
title: 'Home Slider 1',
slug: 'home-slider-1',
id: 331,
images: [
{
title: '',
description: '',
file_extension: 'jpeg',
position: 0,
url: 'https://###images',
type: 0,
link: '',
id: 5773,
},
],
},
]
My Axios :
async mounted() {
const response = await axios.get('/api/')
this.resultsimages = response.data.images_selection.filter(r => r.slug = home-slider-1)
},
Im trying to get the image only in "Home Slider 1" with a filter .filter(r => r.slug = home-slider-1);
But im doing something wrong what will be the best way to target only the home slider 1 ?
EDIT: here is my page where I am not able to loop on the fetched images.
<template>
<div>
<div class="home-slider">
<VueSlickCarousel
:arrows="false"
:dots="true"
:slidesToShow="3"
:rows="1"
:slidesPerRow="3"
:autoplay="true"
:fade="true"
>
<div class="slide1">
<div v-for="result in resultsimages" :key="result.id">
<div class="img1">
<img
v-for="images in result.images"
:key="images.id"
:src="images.url"
/>
</div>
</div>
</div>
</VueSlickCarousel>
</div>
</div>
</template>
<script>
export default {
data() {
return {
resultsimages: [],
data: [],
};
async mounted() {
const { data } = await axios.get("/api/", {
headers: {
"X-AUTH-TOKEN": "####",
"Content-Type": "application/json",
},
});
this.resultsimages = data.images_selection.filter((image) => (image) =>
image.slug === "home-slider-1"
);
},
};
</script>

I heavily formatted your question, especially for the axios part by using only async/await and not a mix of both async/await + .then.
This is how the block should look like
async mounted() {
const { data } = await axios.get('/api/')
this.resultsimages = data.images_selection.filter((image) => (image) => image.slug === 'home-slider-1')
},
Please format your code with more effort next time.

Related

datatable vueJS don´t show data

I´m trayin integrate datatable in my component vue. For this i´m using this library:
https://jamesdordoy.github.io/
i´m install in my proyect, i has configured it, created my component and include in my view, but returned me this message:
Invalid prop: type check failed for prop "data". Expected Object, got Array
my component it´s:
<template>
<div>
<div class="row justify-content-center w-100">
<data-table :data="data" :columns="columns" #on-table-props-changed="reloadTable"></data-table>
</div>
</div>
</template>
<script>
export default {
data() {
return {
url: "/admin/vue/getAllUsers",
data: {},
tableProps: {
search: '',
length: 10,
column: 'id',
dir: 'asc'
},
columns: [
{
label: 'ID',
name: 'id',
orderable: true,
},
{
label: 'Name',
name: 'name',
orderable: true,
},
{
label: 'Email',
name: 'email',
orderable: true,
},
]
}
},
created() {
this.cargar(this.url);
},
methods:{
cargar(url = this.url, options = this.tableProps){
axios.get(url, { params: options })
.then((response) => {
this.data = response.data;
})
.catch((error) => console.error(error));
},
reloadTable(tableProps) {
this.cargar(this.url, tableProps);
}
},
}
</script>
i was trayed with response.data[0] the error disappear but my table it´s empty, i don´t know that i´m doing wrong.
In my controller i have this:
return User::all();
i´m working with laravel 8
thanks for help
you should pass props :items = "data" instead of :data = "data"

Using a method as data inside the app parent

So I'm still learning Vue.js and I got my list working well and I have one question. I will explain what I'm trying to do below as best as possible and I wanted to see if someone could help me with my issue.
So here is the component that I have on the HTML side:
<favorites-edit-component
v-for="(favorite, index) in favorites"
v-bind:index="index"
v-bind:name="favorite.name"
v-bind:key="favorite.id"
v-on:remove="favorites.splice(index, 1)"
></favorites-edit-component>
Here is the vue.js portion that I have:
Vue.component('favorites-edit-component', {
template: `
<div class="column is-half">
<button class="button is-fullwidth is-danger is-outlined mb-0">
<span>{{ name }}</span>
<span class="icon is-small favorite-delete" v-on:click="$emit('remove')">
<i class="fas fa-times"></i>
</span>
</button>
</div>
`,
props: ['name'],
});
new Vue({
el: '#favorites-modal-edit',
data: {
new_favorite_input: '',
favorites: [
{
id: 1,
name: 'Horse',
url: 'www.example.com',
},
{
id: 2,
name: 'Sheep',
url: 'www.example2.com',
},
{
id: 3,
name: 'Octopus',
url: 'www.example2.com',
},
{
id: 4,
name: 'Deer',
url: 'www.example2.com',
},
{
id: 5,
name: 'Hamster',
url: 'www.example2.com',
},
],
next_favorite_id: 6,
},
methods: {
add_new_favorite: function() {
this.favorites.push({
id: this.next_favorite_id++,
name: this.new_favorite_input
})
this.new_favorite_input = ''
},
get_favorite_menu_items: function() {
wp.api.loadPromise.done(function () {
const menus = wp.api.collections.Posts.extend({
url: wpApiSettings.root + 'menus/v1/locations/favorites_launcher',
})
const Menus = new menus();
Menus.fetch().then(posts => {
console.log(posts.items);
return posts.items;
});
})
}
}
});
So as you can see, I have the data: { favorites: [{}] } called inside the vue app and I get this console.log:
Now I built a method called get_favorite_menu_item and this is the return posts.items output inside console.log:
Problem: I don't want to have a manual array of items, I want to be able to pull in the method output and structure that - How would I take a approach on pulling the items?
Could I call something like this:
favorites: this.get_favorite_menu_items?
Here is a JFiddle with all the items: https://jsfiddle.net/5opygkxw/
All help will be appreciated on how to pull in the data.
First I will init favorites to empty array.
then on get_favorite_menu_items() after I will init data from post.item to favorites.
on created() hooks i will call get_favorite_menu_items() to fetch the data when the view is created.
new Vue({
el: '#favorites-modal-edit',
data: {
new_favorite_input: '',
favorites: [],
next_favorite_id: 6,
},
methods: {
add_new_favorite: function() {
this.favorites.push({
id: this.next_favorite_id++,
name: this.new_favorite_input
})
this.new_favorite_input = ''
},
get_favorite_menu_items: function() {
wp.api.loadPromise.done(function () {
const menus = wp.api.collections.Posts.extend({
url: wpApiSettings.root + 'menus/v1/locations/favorites_launcher',
})
const Menus = new menus();
Menus.fetch().then(posts => {
console.log(posts.items);
// need map key also
this.favorites = posts.items;
});
})
}
},
created () {
// fetch the data when the view is created
this.get_favorite_menu_items();
},
});

apply jquery plugin on vue json data

I'm using a vue component to fetch and show data as below:
export default {
data() {
return {
posts: [],
post: {
id: '',
title: '',
rating: '',
ver: ''
},
pagination: {},
}
},
created() {
this.fetchRecentPosts();
},
methods: {
fetchRecentPosts() {
fetch('api/recentposts')
.then(res => res.json())
.then(res => {
this.posts = res.data;
})
}
},
}
I'm also using rateYo plugin to show posts rating.
without using vue.js i'm able to turn my div attribute into star rating by :
$(".rateYo").each(function () {
var rating = $(this).data("rating");
$(this).rateYo({
rating: rating,
starWidth: "13px",
spacing: "3px",
ratedFill: "#ffb300",
normalFill: "#d3d8e4",
readOnly: true
});
});
So, How should I apply it work on evey div inside a v-for loop using vue.js ?
Thanks
var app = new Vue({
el: '#app',
data() {
return {
posts: [
{
id: 1,
title: 'Post One',
rating: 2.5
},
{
id: 2,
title: 'Post Two',
rating: 4.1
}
],
post: {
id: '',
title: '',
rating: '',
ver: ''
},
pagination: {},
}
},
mounted() {
$('.rateYo').each(function() {
$(this).rateYo({
rating: $(this).data('rating'),
starWidth: "13px",
spacing: "3px",
ratedFill: "#ffb300",
normalFill: "#d3d8e4",
readOnly: true
});
});
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rateYo/2.3.2/jquery.rateyo.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/rateYo/2.3.2/jquery.rateyo.min.css">
<div id="app">
<div v-for="(post,index) in posts" :key="index">
<h3>{{ post.title }}</h3>
<div class="rateYo" :data-rating="post.rating"></div>
</div>
</div>

Vue-Slick and v-for with dynamic data

i'm using vue-slick to show my images..
i've tried every solution that i found.. but none is working.
here is my template:
<slick ref="slick" :options="slickOptions">
<img v-for="(item) in categories" :src="'/images/category/'+item.image_url" alt="" class="img-fluid" >
</slick>
and here is my scripts:
data () {
return {
categories:'',
slickOptions: {
dots: true,
infinite: false,
autoplay: false,
arrows : false,
draggable:true,
speed: 1000,
slidesToShow: 1,
slidesToScroll: 1,
},
}
},
mounted() {
let _this = this;
axios({
method: 'post',
url: '/api/category',
data : {'name' : _this.name}
}).then( (response)=> {
console.log(response.data.data);
_this.categories = response.data.data;
}).catch((error) => {
console.log(error.response)
});
},
methods:{
next() {
this.$refs.slick.next();
},
prev() {
this.$refs.slick.prev();
},
reInit() {
this.$refs.slick.reSlick()
}
},
and only loading the image, and the slick is not working...!!?
I have faced the same issue, and what I did to solve this is to put the
v-if="categories.length > 0" on the <slick> tag.
It make the slick won't be created before the data that we want to display contains the data first.
Use below code to reinit slick, and call on success function of response
reInit() {
let currIndex = this.$refs.slick.currentSlide()
this.$refs.slick.destroy()
this.$nextTick(() => {
this.$refs.slick.create()
this.$refs.slick.goTo(currIndex, true)
})
}
I'm assuming your Axios is returning data with the structure you are looking for.
I'm also assuming you are using the vue-slick component and not slick.
You should iterate through a DIV like stated in the documentation. Without Axios, I did this:
In template:
<slick ref="slick" :options="slickOptions">
<div>Escolhe uma configuração...</div>
<div v-for="d in data1"><a class="inline" :href="d.image"><img :src="d.image" alt="">{{ d.text }}</a></div>
</slick>
In Javascript:
data: function() {
return {
data1: [
{ image: 'http://placehold.it/100x100', text: 'Config1' },
{ image: 'http://placehold.it/100x100', text: 'Config2' },
{ image: 'http://placehold.it/100x100', text: 'Config3' },
{ image: 'http://placehold.it/100x100', text: 'Config4' }
]
}

VueJs: Form handling with Vuex and inputs generated with an API

Here's an example of a component:
<script>
export default {
name: 'my-form',
computed: {
myModules() {
return this.$store.state.myModules;
}
}
</script>
<template>
<form>
<p v-for="module in myModules">
<input type="checkbox" :value="module.id" />
<label>module.name</label>
</p>
<button type="submit">Submit</button>
</form>
</template>
The associated store:
state: {
myModules: []
},
mutations: {
setModules(state, modules) {
state.myModules = modules;
}
},
actions: {
getModules({commit}) {
return axios.get('modules')
.then((response) => {
commit('setModules', response.data.modules);
});
}
}
And finally, an example of return of the API "getModules":
modules : [
{
id: 1,
name: 'Module 1',
isActive: false
},
{
id: 2,
name: 'Module 2',
isActive: false
},
{
id: 3,
name: 'Module 3',
isActive: false
}
]
My question: what's the best way to change the "isActive" property of each module to "true" when I check the checkbox corresponding to the associated module, directly in the store?
I know that Vuex's documentation recommends to use "Two-way Computed Property" to manage the forms, but here I don't know the number of modules that the API can potentially return, and I don't know their name.
Thank you in advance!
This is a little bit wicked approach, but it works. You can create an accessor object for every item you access in a loop:
const store = new Vuex.Store({
mutations: {
setActive (state, {index, value}) {
state.modules[index].isActive = value
}
},
state: {
modules : [
{
id: 1,
name: 'Module 1',
isActive: false
},
{
id: 2,
name: 'Module 2',
isActive: false
},
{
id: 3,
name: 'Module 3',
isActive: false
}
]
}
});
const app = new Vue({
el: '#target',
store,
methods: {
model (id) {
const store = this.$store;
// here i return an object with value property that is bound to
// specific module and - thanks to Vue - retains reactivity
return Object.defineProperty({}, 'value', {
get () {
return store.state.modules[id].isActive
},
set (value) {
store.commit('setActive', {index: id, value});
}
});
}
}
})
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/vuex/dist/vuex.min.js"></script>
<div id="target">
<div v-for="(item, id) in $store.state.modules">
Module #{{ item.id }} state: {{ item.isActive }}
</div>
<div v-for="(item, id) in $store.state.modules">
<label>
Module #{{ item.id }}
<input type="checkbox" v-model="model(id).value"/>
</label>
</div>
</div>
This is still quite a messy approach, but at least you don't have to commit mutations directly in template. With a little help of Vue.set() you can use this approach even to overcome standard reactivity caveats.
I have an alternative solution for you. You could make a child component for the checkboxes to clean up the code a bit.
UPD: I just realised that everything that I and #etki proposed is an overkill. I left the old version of my code below in case you still want to take a look. Here is a new one:
const modules = [{
id: 1,
name: 'Module 1',
isActive: true,
},
{
id: 2,
name: 'Module 2',
isActive: false,
},
{
id: 3,
name: 'Module 3',
isActive: false,
},
];
const store = new Vuex.Store({
state: {
myModules: [],
},
mutations: {
SET_MODULES(state, modules) {
state.myModules = modules;
},
TOGGLE_MODULE(state, id) {
state.myModules.some((el) => {
if (el.id === id) {
el.isActive = !el.isActive;
return true;
}
})
}
},
actions: {
getModules({
commit
}) {
return new Promise((fulfill) => {
setTimeout(() => {
commit('SET_MODULES', modules);
fulfill(modules);
}, 500)
});
}
}
});
const app = new Vue({
el: "#app",
store,
data: {},
methods: {
toggle(id) {
console.log(id);
this.$store.commit('TOGGLE_MODULE', id);
}
},
computed: {
myModules() {
return this.$store.state.myModules;
},
output() {
return JSON.stringify(this.myModules, null, 2);
},
},
mounted() {
this.$store.dispatch('getModules').then(() => console.log(this.myModules));
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<script src="https://unpkg.com/vue"></script>
<div id="app">
<form>
<div v-for="data in myModules">
<label :for="data.id">{{ data.name }}: {{data.isActive}}</label>
<input type="checkbox" :id="data.id" :name="'checkbox-' + data.id" :checked="data.isActive" #change="toggle(data.id)">
</div>
</form>
<h3>Vuex state:</h3>
<pre v-text="output"></pre>
</div>
As you can see above you could just call a function on input change and pass an id as a parameter to a method that fires vuex action.
The old version of my code.
A new one on jsfiddle