Loop images from strapi with 11ty - strapi

I need your help!
I'm trying to fetch strapi data using 11ty following this guide:
https://strapi.io/documentation/developer-docs/latest/developer-resources/content-api/integrations/11ty.html#get-request-your-collection-type
I've handled with all data excepting images.
Fetching code:
const { default: axios } = require('axios');
module.exports = async () => {
try {
const res = await axios.get('http://localhost:1337/articles');
return res.data;
} catch (error) {
console.error(error);
}
};
11ty code:
---
title: Articles
layout: default.liquid
pagination:
data: articles
size: 100
alias: articles
---
<div class="works content">
<div class="container">
<div class="works__items">
{%- for article in articles -%}
<div class="works__item">
<div class="works__image">
<img src="{{ article.image.url }}" alt="{{ work.data.title }}">
</div>
<div class="works__content">
<div class="works__title">
<h3>{{ article.title }}</h3>
<span>
{{ article.year }}
</span>
</div>
<div class="works__description">
<p>{{article.content }}</p>
</div>
</div>
</div>
{%- endfor -%}
</div>
</div>
</div>
</div>
Json:
[
{
"id": 1,
"title": "My first article post",
"content": "This is the first strapi post",
"year": 2021,
"users": null,
"published_at": "2021-09-19T12:52:24.304Z",
"created_at": "2021-09-19T12:10:38.253Z",
"updated_at": "2021-09-19T17:39:17.072Z",
"image": [
{
"id": 4,
"name": "steve-johnson-3Sf_G9m0gcQ-unsplash.jpg",
"alternativeText": "",
"caption": "",
"width": 1920,
"height": 1287,
"formats": {
"thumbnail": {
"name": "thumbnail_steve-johnson-3Sf_G9m0gcQ-unsplash.jpg",
"hash": "thumbnail_steve_johnson_3_Sf_G9m0gc_Q_unsplash_106d5a6cc8",
"ext": ".jpg",
"mime": "image/jpeg",
"width": 233,
"height": 156,
"size": 11.65,
"path": null,
"url": "/uploads/thumbnail_steve_johnson_3_Sf_G9m0gc_Q_unsplash_106d5a6cc8.jpg"
},
"large": {
"name": "large_steve-johnson-3Sf_G9m0gcQ-unsplash.jpg",
"hash": "large_steve_johnson_3_Sf_G9m0gc_Q_unsplash_106d5a6cc8",
"ext": ".jpg",
"mime": "image/jpeg",
"width": 1000,
"height": 670,
"size": 221.22,
"path": null,
"url": "/uploads/large_steve_johnson_3_Sf_G9m0gc_Q_unsplash_106d5a6cc8.jpg"
},
"medium": {
"name": "medium_steve-johnson-3Sf_G9m0gcQ-unsplash.jpg",
"hash": "medium_steve_johnson_3_Sf_G9m0gc_Q_unsplash_106d5a6cc8",
"ext": ".jpg",
"mime": "image/jpeg",
"width": 750,
"height": 503,
"size": 123.25,
"path": null,
"url": "/uploads/medium_steve_johnson_3_Sf_G9m0gc_Q_unsplash_106d5a6cc8.jpg"
},
"small": {
"name": "small_steve-johnson-3Sf_G9m0gcQ-unsplash.jpg",
"hash": "small_steve_johnson_3_Sf_G9m0gc_Q_unsplash_106d5a6cc8",
"ext": ".jpg",
"mime": "image/jpeg",
"width": 500,
"height": 335,
"size": 54.99,
"path": null,
"url": "/uploads/small_steve_johnson_3_Sf_G9m0gc_Q_unsplash_106d5a6cc8.jpg"
}
},
"hash": "steve_johnson_3_Sf_G9m0gc_Q_unsplash_106d5a6cc8",
"ext": ".jpg",
"mime": "image/jpeg",
"size": 698.21,
"url": "/uploads/steve_johnson_3_Sf_G9m0gc_Q_unsplash_106d5a6cc8.jpg",
"previewUrl": null,
"provider": "local",
"provider_metadata": null,
"created_at": "2021-09-19T12:10:16.836Z",
"updated_at": "2021-09-19T12:10:16.845Z"
}
]
},
{
"id": 2,
"title": "Second article",
"content": "The second article",
"year": 2001,
"users": null,
"published_at": "2021-09-19T17:36:34.649Z",
"created_at": "2021-09-19T17:36:32.774Z",
"updated_at": "2021-09-19T17:36:34.665Z",
"image": [ ]
},
{
"id": 3,
"title": "Third article",
"content": "Third article",
"year": 2134,
"users": null,
"published_at": "2021-09-19T17:38:07.022Z",
"created_at": "2021-09-19T17:38:05.706Z",
"updated_at": "2021-09-19T17:38:07.036Z",
"image": [ ]
}
]
Thank you a lot!

Well, from what I understood, you need to render the images from the image key. To do this, you can just loop over the image array in articles and then access it's properties like below:
<div class="works content">
<div class="container">
<div class="works__items">
{%- for article in articles -%}
<div class="works__item">
{%- for image in article.image -%}
<div class="works__image">
<img src="{{ image.url }}" alt="{{ work.data.title }}">
</div>
{%- endfor -%}
<div class="works__content">
<div class="works__title">
<h3>{{ article.title }}</h3>
<span>
{{ article.year }}
</span>
</div>
<div class="works__description">
<p>{{article.content }}</p>
</div>
</div>
</div>
{%- endfor -%}
</div>
</div>
</div>
</div>

There are 3 images so you need to get the right size instead of just {{article.image.url}}.
From my experience it's actually much better to transform such a "complex" api response to something much more suitable for template. You can do that in your data file. It's much easier to manipulate data in data file then inside template.

Related

How to make dynamic menu and submenu Vue 3?

Im stuck and need some help on how to looping dynamic menu and submenu with Vue.Js 3.
My props.menus data send from Controller:
[
{
"id": 1,
"name": "Menu 1",
"active": 1,
"created_at": "2022-11-20T03:27:47.000000Z",
"updated_at": "2022-11-20T03:27:47.000000Z",
"sub_menus": [
{
"id": 1,
"menuId": 1,
"name": "Sub Menu 1",
"active": 1,
"created_at": "2022-11-20T03:27:57.000000Z",
"updated_at": "2022-11-20T03:27:57.000000Z"
},
{
"id": 2,
"menuId": 1,
"name": "Sub Menu 2",
"active": 1,
"created_at": "2022-11-20T06:31:59.000000Z",
"updated_at": "2022-11-20T06:31:59.000000Z"
}
]
},
{
"id": 2,
"name": "Menu 2",
"active": 1,
"created_at": "2022-11-20T12:02:16.000000Z",
"updated_at": "2022-11-20T12:02:16.000000Z",
"sub_menus": []
}
]
And this is my controller index:
public function index()
{
Inertia::setRootView('frontend');
$menus = Menu::with('subMenus')->where('active', 1)->get();
return Inertia::render('Frontend/Home', [
'menus' => $menus,
]);
}
It should be:
Menu 1
Sub Menu 1
Sub Menu 2
Menu 2
This is my current code, and i wonder its still not working:
<div class="nav-link dropdown-toggle" v-for="(menu, menuIndex) in menus" :key="menuIndex" role="button"
id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ menu.name }}
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink" v-for="(item, subMenuIndex) in menu.sub_menus"
:key="subMenuIndex">
<a class="dropdown-item" href="#">{{ item.name }}</a>
</div>
</div>
But with my current code, its showing not correctly:
Menu 1
Sub Menu 1
Menu 2
Sub Menu 1
Thanks before

Shentao/VueMultiselect is not accepting api json response in :option="" vue3 composition api

Template
the category is API JSON Response asenter image description here
[{ "id": 1, "name": "sadi" }, { "id": 2, "name":"kurtha" }, { "id": 3, "name": "shirt" }]
it throw error by Uncaught (in promise) TypeError: this.options.concat is not a function
Error Image
<div v-if="category">
{{ category }}
<VueMultiselect
class="text-dark"
track-by="name" label="name"
v-model="form.category"
:options="category"
:loading="true">
</VueMultiselect>
</div>
But if I store the same response in the array manually it works,
Template
<div v-if="category">
{{ category }}
<VueMultiselect
class="text-dark"
track-by="name" label="name"
v-model="form.category"
:options="api"
:loading="true">
</VueMultiselect>
</div>
Script
const api = [
{ "id": "1", "name": "sadi" },
{ "id": "2", "name": "kurtha" },
{ "id": "3", "name": "shirt" }
];
Error when I put category API response
Working Image but manuall

Shopify theme editor crashing after creating sections for the homepage

I'm trying to create a Gallery section for shopify using liquid and Schema. After working a bit on the code, the theme editor renders unresponsive or crashes. I've tried deleting the theme I'm editing, and publishing a backup but the backup theme's editor also crashes (even though the new sections does not even exist on that version).
After a day or two it seems to be working fine, but if I create another section to test, it goes unresponsive again. Don't really know what I'm missing here. At first, Shopify support told me it was on their side, but it is not, because it happens when I create a new section. Their solution was to update my theme which is not happening because I've donde extensive customization and theme versioning is terrible with Shopify. Anyways, here's the section I'm trying to create:
<div class="grid grid--no-gutters image-bar image-bar--{{ section.settings.section_height }}">
{% for block in section.blocks %}
<div class="image-wrap" style="background-image: url('{{ block.settings.image | img_url: '500x500' }}');">
<h3>{{ block.settings.mention-text }}</h3>
</div>
{% endfor %}
</div>
{% schema %}
{
"name": "Galeria",
"settings": [
{
"type": "select",
"id": "per-row",
"label": "Images per row",
"options": [
{
"value": "49.5%",
"label": "2 per row"
},
{
"value": "33%",
"label": "3 per row"
},
{
"value": "24.5%",
"label": "4 per row"
}
],
"default": "24.5%"
},
{
"type": "select",
"id": "height",
"label": "Image Height",
"options": [
{
"value": "100px",
"label": "100px"
},
{
"value": "200px",
"label": "200px"
},
{
"value": "300px",
"label": "300px"
},
{
"value": "410px",
"label": "450px"
},
{
"value": "500px",
"label": "500px"
}
],
"default": "500px"
}
],
"blocks": [
{
"type": "image",
"name": "Image Block",
"settings": [
{
"type": "image_picker",
"id": "image",
"label": "Image"
},
{
"type": "text",
"id": "mention_text",
"label": "Mention user",
"placeholder": "#"
}
]
}
],
"presets": [
{
"category": "Galeria",
"name": "Galeria"
}
]
}
{% endschema %}
{% style %}
.image-wrap {
display: inline-block;
width: {{section.settings.per-row}};
height: {{section.settings.height}};
background-size: 100%;
}
.page-width.galeria-testimonial {
width: 90%;
margin: 0 auto;
}
{% endstyle %}
I believe you need to delete the section info from your settings_data.json file. All your sections created has JSON objects stored here that is at times not removed upon file deletion and you need to manually delete it. I suggest if you open that file and look for Galeria and delete the json object for that section.
This article can help in your understanding of themes.
An additional suggestion is to begin versioning your theme outside of Shopify you can have a versioning and use staging themes to test new features/changes in order for better version control and testing without the hassle of messing up your live site.

Vue js v-for not working when array passed from laravel backend

I don't get it for some reason when i pass array through props v-for wont work and only difference i can see from directly writing data is that one passed from props don't have spaces in between.
I am using laravel and through blade im passing data to vue, data is array of all photos with informations. But that data won't list through all photos and display div's.
Let me show you my code:
This is what i have in blade template:
<picture-upload
:input_value="'{{ json_encode($profilephotos) }}'"
:bind_user="'{{ $profile->id }}'"
:input_name="'profilephoto'"
:post_url="'{{ route('photouploads') }}'"
:type="'profilephoto'"
></picture-upload>
I don't think that json_encode make difference in this case but i tried it any way.
And this is what i have in my photos.vue file
props: ['input_name', 'post_url', 'bind_user', 'type', 'input_value'],
data() {
return {
files: [],
uploads: this.input_value,
items: [
{"id":110,"user_id":28,"type":"profilephoto","name":"5.jpg","mime":"image/jpeg","extension":"jpg","path":"3f49191095d302fb7e66ce037dd5efa111287e8230964ad8a3170687ca4336a1","size":192445,"created_at":"2019-04-23 16:04:01","updated_at":"2019-04-23 16:04:01"},
{"id":111,"user_id":28,"type":"profilephoto","name":"4.jpg","mime":"image/jpeg","extension":"jpg","path":"0bd693c2cd1ab5ec2c7223fc6a92356ab68c52e8cc0b7d5d5aa5b4a230cf015b","size":193223,"created_at":"2019-04-23 21:58:52","updated_at":"2019-04-23 21:58:52"},
{"id":112,"user_id":28,"type":"profilephoto","name":"5.jpg","mime":"image/jpeg","extension":"jpg","path":"0bd693c2cd1ab5ec2c7223fc6a92356ab68c52e8cc0b7d5d5aa5b4a230cf015b","size":192445,"created_at":"2019-04-23 21:58:52","updated_at":"2019-04-23 21:58:52"},
{"id":113,"user_id":28,"type":"profilephoto","name":"4.jpg","mime":"image/jpeg","extension":"jpg","path":"ffe6f95d10c5249390fcea140fe15a1fb57f5d29626a947e4a999db50f3ea295","size":193223,"created_at":"2019-04-23 22:00:10","updated_at":"2019-04-23 22:00:10"},
{"id":114,"user_id":28,"type":"profilephoto","name":"4.jpg","mime":"image/jpeg","extension":"jpg","path":"75a00a901f1a01a0267d44bebc8574efa9eb7a7edfd395e29dabb289efb353ac","size":193223,"created_at":"2019-04-23 22:05:32","updated_at":"2019-04-23 22:05:32"}
]
}
},
So input_value is what is passed from blade template, and items is what i added manually for testing, items is exactly the same as what i see when i output data in frontend.
Here is what i have in .vue <template> section
{{ items }}
<li v-for="item in items">
{{ item.type }}
</li>
{{ uploads }}
<div v-for="upload in uploads">
{{ upload.type }}
</div>
So items should output complete array and v-for should filter and output foreach item in that array, which should go the same for uploads but problem is uploads not working.
This is what i actually get in frontent
For {{ items }}
[ { "id": 110, "user_id": 28, "type": "profilephoto", "name": "5.jpg", "mime": "image/jpeg", "extension": "jpg", "path": "3f49191095d302fb7e66ce037dd5efa111287e8230964ad8a3170687ca4336a1", "size": 192445, "created_at": "2019-04-23 16:04:01", "updated_at": "2019-04-23 16:04:01" }, { "id": 111, "user_id": 28, "type": "profilephoto", "name": "4.jpg", "mime": "image/jpeg", "extension": "jpg", "path": "0bd693c2cd1ab5ec2c7223fc6a92356ab68c52e8cc0b7d5d5aa5b4a230cf015b", "size": 193223, "created_at": "2019-04-23 21:58:52", "updated_at": "2019-04-23 21:58:52" }, { "id": 112, "user_id": 28, "type": "profilephoto", "name": "5.jpg", "mime": "image/jpeg", "extension": "jpg", "path": "0bd693c2cd1ab5ec2c7223fc6a92356ab68c52e8cc0b7d5d5aa5b4a230cf015b", "size": 192445, "created_at": "2019-04-23 21:58:52", "updated_at": "2019-04-23 21:58:52" }, { "id": 113, "user_id": 28, "type": "profilephoto", "name": "4.jpg", "mime": "image/jpeg", "extension": "jpg", "path": "ffe6f95d10c5249390fcea140fe15a1fb57f5d29626a947e4a999db50f3ea295", "size": 193223, "created_at": "2019-04-23 22:00:10", "updated_at": "2019-04-23 22:00:10" }, { "id": 114, "user_id": 28, "type": "profilephoto", "name": "4.jpg", "mime": "image/jpeg", "extension": "jpg", "path": "75a00a901f1a01a0267d44bebc8574efa9eb7a7edfd395e29dabb289efb353ac", "size": 193223, "created_at": "2019-04-23 22:05:32", "updated_at": "2019-04-23 22:05:32" } ]
And there v-for="item in items" logic works, if i do
<li v-for="item in items">
{{ item.type }}
</li>
I will get list of item.type
The problem happens if i do exactly the same with uploads something is not working.
If i test output of {{ uploads }} i will get exactly same array as with items except there are spaces between things in array.
This is output of {{ uploads }}
[{"id":110,"user_id":28,"type":"profilephoto","name":"5.jpg","mime":"image/jpeg","extension":"jpg","path":"3f49191095d302fb7e66ce037dd5efa111287e8230964ad8a3170687ca4336a1","size":192445,"created_at":"2019-04-23 16:04:01","updated_at":"2019-04-23 16:04:01"},{"id":111,"user_id":28,"type":"profilephoto","name":"4.jpg","mime":"image/jpeg","extension":"jpg","path":"0bd693c2cd1ab5ec2c7223fc6a92356ab68c52e8cc0b7d5d5aa5b4a230cf015b","size":193223,"created_at":"2019-04-23 21:58:52","updated_at":"2019-04-23 21:58:52"},{"id":112,"user_id":28,"type":"profilephoto","name":"5.jpg","mime":"image/jpeg","extension":"jpg","path":"0bd693c2cd1ab5ec2c7223fc6a92356ab68c52e8cc0b7d5d5aa5b4a230cf015b","size":192445,"created_at":"2019-04-23 21:58:52","updated_at":"2019-04-23 21:58:52"},{"id":113,"user_id":28,"type":"profilephoto","name":"4.jpg","mime":"image/jpeg","extension":"jpg","path":"ffe6f95d10c5249390fcea140fe15a1fb57f5d29626a947e4a999db50f3ea295","size":193223,"created_at":"2019-04-23 22:00:10","updated_at":"2019-04-23 22:00:10"},{"id":114,"user_id":28,"type":"profilephoto","name":"4.jpg","mime":"image/jpeg","extension":"jpg","path":"75a00a901f1a01a0267d44bebc8574efa9eb7a7edfd395e29dabb289efb353ac","size":193223,"created_at":"2019-04-23 22:05:32","updated_at":"2019-04-23 22:05:32"},{"id":115,"user_id":28,"type":"profilephoto","name":"4.jpg","mime":"image/jpeg","extension":"jpg","path":"c0db13b85c255a30b8466ca5778cad05d06f20f2cf12a3db46e9b6a7d182fdd8","size":193223,"created_at":"2019-04-23 22:14:37","updated_at":"2019-04-23 22:14:37"},{"id":116,"user_id":28,"type":"profilephoto","name":"4.jpg","mime":"image/jpeg","extension":"jpg","path":"3591cedc64c8f3638d71643291ce2e37d697dbcdfe08c715254d94237b93b1a1","size":193223,"created_at":"2019-04-23 22:21:37","updated_at":"2019-04-23 22:21:37"}]
And if i try to do
<div v-for="upload in uploads">
{{ upload.type }}
</div>
I get whole bunch of empty div's without upload.type output. Plus i have like 20 images in total, i get like 200 empty div's.
This confuses me alot as why it is happening like this, any suggestions?
with »Quotation Singletick« "' you enter the »string« mode - which is not a variable but the chars you enter/ Laravel suplies.
Something from the best practice side: Don't use underscore in attrbutes/variable/prop names. Vue converts ":input-value" (kebab-case) to "inputValue" (camelCase) for you inside the component.
Last but not least. Make sure to always supply a key for your v-for list. Like
<li v-for="(item,index) in items" :key="index"></li>
Hope that helps

Fix for chained select vue js component

I have 2 select dropdown boxes, one for home types and another for duration, i have been able to fetch data into the hometype dropdown but the duration dropdown is not fetching data.
Anyone, please help resolve
This is a vue component
<script>
export default {
mounted() {
console.log('Component mounted.')
},
data(){
return {
selectedHomeType: 0,
HomeTypes: [],
selectedDuration: 0,
durations: []
}
},
methods:{
getHousetypes: function(){
axios.get('api/getHousetypes')
.then(function (response) {
this.HomeTypes = response.data;
}.bind(this));
},
getDuration: function() {
axios.get('api/getDuration',{
params: {
house_type_id: this.selectedHomeType
}
}).then(function(response){
this.Durations = response.data;
}.bind(this));
}
},
created: function(){
this.getHousetypes()
}
}
</script>
<template>
<div>
<div class=" col-xs-4 text-center">
<label>Select HomeType:</label><div class="col-xs-4 text-center">
<select name="Housetype" class='form-control centre' v-model='selectedHomeType' #change='getHousetypes()'>
<option value='0' >Select HomeType </option>
<option v-for='HomeType in HomeTypes' :value='HomeType.id' v-bind:key="HomeType.id">
{{ HomeType.House_Type }}
</option>
</select>
</div>
</div>
<div class="form-group col-xs-4 text-center">
<div class="form-group">
<label>Select Durations:</label>
<select class='form-control' v-model='selectedDuration'>
<option value='0' >Select Durations</option>
<option v-for='duration in durations' :value='duration.id' v-bind:key="duration.id">
{{ duration.duration }}
</option>
</select>
</div>
</div>
</div>
</template>
Sample JSON Data
Data for Hometypes
{
"success": [
{
"id": 1,
"created_at": "2019-09-26 08:44:00",
"updated_at": "2019-09-26 08:43:58",
"House_Type": "1 Bedroom",
"status": "1"
},
{
"id": 2,
"created_at": "2019-09-26 08:44:00",
"updated_at": "2019-09-26 08:43:58",
"House_Type": "2 Bedroom",
"status": "1"
},
{
"id": 3,
"created_at": "2019-09-26 08:44:00",
"updated_at": "2019-09-26 08:43:58",
"House_Type": "3 Bedroom",
"status": "1"
},
{
"id": 4,
"created_at": "2019-09-26 08:44:00",
"updated_at": "2019-09-26 08:43:58",
"House_Type": "3 Bedroom Penthouse",
"status": "1"
},
{
"id": 5,
"created_at": "2019-09-26 08:44:00",
"updated_at": "2019-09-26 08:43:58",
"House_Type": "4 Bedroom",
"status": "1"
}
]
}
Data for Durations
[
{
"id": 13,
"created_at": "2019-09-26 08:46:15",
"updated_at": "2019-09-26 08:46:17",
"house_type_id": 5,
"duration": "9 Months",
"status": "1"
},
{
"id": 14,
"created_at": "2019-09-26 08:46:15",
"updated_at": "2019-09-26 08:46:17",
"house_type_id": 5,
"duration": "6 Months",
"status": "1"
},
{
"id": 15,
"created_at": "2019-09-26 08:46:15",
"updated_at": "2019-09-26 08:46:17",
"house_type_id": 5,
"duration": "3 Months",
"status": "1"
}
]
See Image RepresentationOn Select HomeType 1 Bedroom Durations for 1 Bedroom show display eg 3 months, 6 months and 9 months in the Durations Select Box
I think you mistakenly connected the wrong ajax method to the change event on the house type select box.
I think your logic is to update durations when you change the house type, but you are currently refreshing the house types available:
<select name="Housetype" class='form-control centre' v-model='selectedHomeType' #change='getDuration()'>
<option value='0' >Select HomeType </option>
<option v-for='HomeType in HomeTypes' :value='HomeType.id' v-bind:key="HomeType.id">
{{ HomeType.House_Type }}
</option>
</select>
Update
Make sure your variable names are correct throught the code.
For example, you first define durations variable, but then try to assign this.Durations (notice the capital letter).
This might not be the issue, but may be confusing for other programmers.
I would suggest to use snake_case or camelCase to name your variables and stick to that convention you have chosen in your code. Usually, PascalCase is used for class names.
To quickly read more about different types of casing, check out this medium post
Update #2
To display data in Vue you can use {{ your_variable_here }} syntax anywhere in your component template.
That's really simple, just put the printing syntax where you need in the html template.
For example, to print the selection you can check if selectedHomeType's value is different than 0 (because 0 would be "Select HomeType"'s index) with the v-if directive. Then inside this div put the code that you want to display when the given if condition is true.
In there you can use the selectedHomeType value to get the chosen element from the homeTypes array.
<div v-if="selectedHomeType !== 0">
<p>The selected HomeType is: {{ this.homeTypes[selectedHomeType - 1].House_Type }}</p>
</div>

Resources