Related

how to access nested json object property using nuxtjs and v-for

I want to access a nested object using v-for in nuxtjs,I have a get request using Axios to an API and response data is stored in a variable named CategoriesData look at the code below.
asyncData(context) {
return axios
.get("https://lavazemesakhteman.com/wp-json/wc/v3/products/categories", {
params: {
per_page: 10,
page: 1,
},
})
.then((res) => {
return {
CategoriesData: res.data,
};
})
.catch((e) => context.error(e));}
at this point, everything is good and all API response is stored in CategoriesData, my problem starts when I want to iterate over the nested object and display or use its property, pay attention to the code below:
<ul>
<li v-for="categories in CategoriesData" :key="categories.id">
{{ categories.name }}
{{ categories.image }}
</li>
</ul>
the result is:
I want to display and use categories.image[0].src for example src only not the whole object, the API response is pictured below:
this is a part of JSON code:
"display": "default",
"image": {
"id": 10443,
"date_created": "2022-04-30T05:45:44",
"date_created_gmt": "2022-04-30T01:15:44",
"date_modified": "2022-04-30T05:46:36",
"date_modified_gmt": "2022-04-30T01:16:36",
"src": "https://lavazemesakhteman.com/wp-content/uploads/2022/04/Benkan-Connections2.jpg",
"name": "Benkan Connections",
"alt": "فروشگاه لوازم ساختمان عرضه کننده محصولاتی باکیفیت و همچنین با بهترین قیمت در تمام کشور هست."
},
when is used categories.image.src:
<ul>
<li v-for="categories in CategoriesData" :key="categories.id">
{{ categories.name }}
{{ categories.image.src }}
</li>
</ul>
I get the below error:
Cannot read properties of null (reading 'src')
You can access nested data using the same . notation you already use to get the first field, so you would need to write something like {{ categories.image.src }}.
<template>
<ul>
<li v-for="category in CategoriesData" :key="category.id">
{{ category.name }}
<img :src="category.image.src">
</li>
</ul>
</template>
Note: You named the variable in your v-for as a plural, while the data it holds is singular. As each item in the list of categories is an individual category.
Going to the API itself, located here: http://lavazemesakhteman.com/wp-json/wc/v3/products/categories
Showed that sometimes your image can be null, hence checking for this exception is a nice thing to do
<img v-if="category.image" :src="category.image.src">
Depending on your project and how it's setup, you could even use Optional Chaining like this
<img :src="category.image?.src">
Otherwise, this uglier form is also available
<img :src="category.image && category.image.src">

I almost have a page numbering with comments but something fails with mounted (vue.js)

Here you have the HTML:
<div>
<nav>
<ul class="pagination">
<li #click.prevent="paginaAnterior">Anterior</li>
<li #click.prevent="contenidoPagina(pagina)" v-for="pagina in totalPaginas()" class="page-item">{{ pagina }}</li>
<li #click.prevent="paginaSiguiente">Siguiente</li>
</ul>
</nav>
<article class="caja__articulo-noticias" v-for="item in datosPaginados">
<p>
{{ item.nombre }} {{ item.fields.Nombre }} {{ item.apellido }} {{ item.fields.Apellidos }}
</p>
<p>
{{ item.comentario }} {{ item.fields.Comentario }}
</p>
</article>
</div>
And this is the vue.js. I would like to show the first page of the comments when the website is loaded
mounted: function () {
this.obtenerDatosNoticia2();
**this.contenidoPagina(1);** // it doesn´t shows me the first page
},
methods: {
totalPaginas: function () {
return Math.ceil(this.infosNoticia2.length / this.elementosPorPagina);
},
contenidoPagina: function(numeroPagina){
this.paginaActual = numeroPagina;
this.datosPaginados = [];
let inicio = (numeroPagina * this.elementosPorPagina) - this.elementosPorPagina;
let fin = (numeroPagina * this.elementosPorPagina);
this.datosPaginados = this.infosNoticia2.slice(inicio,fin);
},
paginaAnterior: function () {
if(this.paginaActual > 1) {
this.paginaActual = this.paginaActual - 1;
}
this.contenidoPagina(this.paginaActual);
},
paginaSiguiente: function () {
if(this.paginaActual < this.totalPaginas()) {
this.paginaActual = this.paginaActual + 1;
}
this.contenidoPagina(this.paginaActual);
}
}
})
To put you in context I'm doing a blog about music. I have a section with news about music, singers... and at the bottom I've made a kind of number pagination to list all the comments that people can add. The number pagination works right, the problem is that I'd like to see the first page of the comments when you're in this section because I only see the number pagination (1, 2, 3, 4...) and you've to click in each one to see the comments.

Vue - Bug or design with template vslots

I notice that some of my computed properties don't fire when they call upon the same data. As a super-simplistic example let's say I have this:
<template v-for="item in foo" v-slot:['sameSlot`]="{sameBlah}">
{{ JSON.stringify(item) }}
</template>
<template v-for="item in bar" v-slot:['sameSlot`]="{sameBlah}">
{{ JSON.stringify(item) }}
</template>
<template v-for="item in baz" v-slot:['sameSlot`]="{sameBlah}">
{{ JSON.stringify(item) }}
</template>
...
data: () => ({
someData: [
{type:'foo', value: 1},
{type:'bar', value: 2},
{type:'baz', value: 3},
],
});
computed: {
foo() {
console.log('Hello from foo');
return this.someData.filter(f => f.type === 'foo');
},
bar() {
console.log('Hello from bar');
return this.someData.filter(f => f.type === 'bar');
},
baz() {
console.log('Hello from baz');
return this.someData.filter(f => f.type === 'baz');
},
}
If I run that, I only see console output from one of the computed methods, not all. Same with seeing results in the templates. Is this by design?
BTW I'm aware I could eliminate the computed properties by creating a method where a filter key could be passed in, but that doesn't showcase this 'issue'.
The code in the post targets the same slot 3 times, so Vue completely ignores the first 2 without running any of the code in the first two templates even once.
This is a smart feature to minimize workload because it's not sensible to target the same slot more than once to begin with. If anything, maybe there should be a warning from the compiler in this situation.
You could even have code that tries to use variables which don't exist, and there will be no compiler warning. For example:
<!-- First call: completely ignored, no error -->
<template v-for="item in notDefinedOnTheInstance" v-slot:[`sameSlot`]="{sameBlah}">
{{ JSON.stringify(item) }}
</template>
<!-- Second call: used for the slot -->
<template v-for="item in baz" v-slot:[`sameSlot`]="{sameBlah}">
{{ JSON.stringify(item) }}
</template>
Despite not existing in the instance, notDefinedOnTheInstance won't throw a warning because that whole section has been ignored. So it's for this reason that you also don't see the computeds output in the console, because they never run.

How in livewire use route by its name?

In my laravel 7 /livewire 1.3 / turbolinks:5 / alpine#v2 app I have route defined
Route::livewire('/hostel/{slug}', 'hostel.hostel-view-page')->name('hostel-view-page');
When I use it :
<a href="{{ route('hostel-view-page', $hostelsIsHomepageSpotlight->slug) }}" >
Title
</a>
it does not work as reactive, as all page is reloaded. I prefer to name of this route, not like :
<a href="/hostel/{{ $hostelsIsHomepageSpotlight->slug }}" >
Title
</a>
Which is a valid way ?
Thanks!
Try this, it works well for me:
Route::group(['prefix' => 'admin',
'as' => 'admin.',
'middleware' => 'your:middleware',
], function () {
Route::livewire('your-url-here', 'your-livewire-class-here')
->name('whatever.you.want');
});

How to remove Vuejs "scope is undefined' warning?

As a beginner with Vue.js, I have a component that looks like this:
<template>
<div>
<a href="{{ data.uk_store_link }}">
{{ data.title }} - {{ data.artist.name }}
</a>
</div>
</template>
<script>
export default {
props: ['data']
}
</script>
"data.artist.name" is present and correct in the object that is passed to the data prop. But how can I get rid of the warning that pops up about the nested artist name?
[Vue warn]: Error when evaluating expression "data.artist.name":
TypeError: scope.data.artist is undefined (found in component:
<release>)
ETA: Ah, sorry, yes, it would have been helpful to show the "data":
{ "id": 23182, "title": "Music from 'Likely Stories'",
"uk_store_link":
"http://store.roughtraderecords.com/...html",
"artist": { "id": 1176, "name": "Jarvis Cocker" } }
I've stripped out some fields there for brevity, but hopefully this demonstrates that data.artist.name does actually exist. It certainly gets successfully output to the page, despite the warning.
{{ data.artist ? data.artist.name : '' }}