why images dont show in vue? - vue.js

i pass an image address to a component , But it doesnt show that !!
i also use require() But nothing .
this is component code
<div >
<img :src="require(data.src)" class="ccard-right-img" alt="" />
</div>
and this is paent component code :
<product-card
:data="{cat: 'category', title: 'card title', src: '~/static/1.png' }"
/>
how can i fix it ??

finally i didi it like this:
<img :src="require('#/static/'+data.src+'.png')" class="ccard-right-img" alt="" />

Related

Dynamic Heroicons in Vue.js

I assign the heroicon to a variable from my list of menu items.
const navigation = [{ name: 'Dashboard', icon: TemplateIcon, href: '#', current: true }]
Then I try to display the icon.
<li v-for="item in navigation" class="relative px-6 py-3">
<TemplateIcon class="h-5 w-5" />
<item.icon class="h-5 w-5" />
</li>
The template icon is only shown once, but should be shown twice.
I have already tried this
<{{item.icon}} class="h-5 w-5" />
{{item.icon}}
<svg><path :d="item.icon"></path></svg>
thx for help
You can use Dynamic component approach which is useful to dynamically switch between components.
This can be achieve by using Vue's <component> element with the special :is attribute.
Demo :
new Vue({
el: '#app',
data: {
navigation: [{ icon: 'H3' }]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="container">
<div v-for="(item, index) in navigation" :key="index">
<component :is="item.icon">Hello</component>
</div>
</div>
</div>
You should use the component component in vue.
You can find the documentation for it here: https://vuejs.org/guide/essentials/component-basics.html#dynamic-components
tldr, pass your component in the is prop
<component :is="item.icon" class="h-5 w-5" />

Src binding in vue is not showing images

I have created an Array with three objects and a loop over it in my template.
It is working fine for getting other data and src data but it is not showing my images.
Does anybody what should i do?
sandbox link to my project
And here is my template code
<div
class="box m-3"
#click="selectBox(item.id)"
v-for="item in boxData"
:key="item.id"
:class="{
'border-select': selected(item.id),
}"
>
<p>{{ item.name }}</p>
<img :src="item.src" width="60" alt="" />
src: {{item.src}}
</div>
My data
boxData: [
{ id: 1, name: "object 1", src: "#/assets/power(1).png" },
{ id: 2, name: "object 2", src: "#/assets/power(1).png" },
{ id: 3, name: "object 3", src: "#/assets/power(1).png" },
],
Solution 1:
If you don't want to use Webpack assets from the assets directory, you can add the images to the static directory.
In your code, you can then reference these files relative to the root (/):
<!-- Static image from static directory -->
<img src="/my-image.png" />
<!-- webpacked image from assets directory -->
<img src="~/assets/my-image-2.png" />
Nuxt doesn't change this path, so if you customize your router.base then you'll need to make sure to add that manually to your paths. For example:
<img :src="`${yourPrefix}/my-image.png`" />
Solution 2: When working with dynamic images you will need to use require
<img :src="require(`~/assets/img/${image}.jpg`)" />
Image not displaying in loop Vue.js
<img :src="require(`#/assets/${item.src}`)" width="60" alt="" /> src: {{ item.src }}
It worked like this

Algolia vue auto select facets

I am developing an algolia search solution for an ecommerce app with around ~30000 products.
I tried to use the <ais-configure/> component to filter my results before showing them on the page, as I am working with different pages for each category of products and some facet filters also need to be applied if a user was to click on a promotion which would lead to this search result in the code below.
The problem is:
Whenever I use the filters in <ais-configure/> the same filters are not picked up by my <ais-refinement-list/> component which should have the refined facets highlighted.
The below code is not working but descriptive enough for the problem.
Template
<ais-instant-search :search-client.camel="searchClient" index-name="products">
<ais-configure
:filters.camel="searchParameters.filters"
:facet-filters.camel="searchParameters.facetFilters"
/>
<ais-infinite-hits>
<div
slot="loadMore"
slot-scope="{ isLastPage, refineNext }"
class="w-full my-12 px-6 text-sm-black-primary"
>
<button
class="
w-full
h-20
border-4
rounded-md
border-sm-black-primary
font-semibold
text-xl
mb-24
"
:disabled="isLastPage"
#click="refineNext"
>
See more
</button>
</div>
</ais-infinite-hits>
<products-filter-section>
<div v-for="(filterType, id) in filterTypes" :key="id">
<ais-refinement-list :attribute="filterType" searchable show-more>
<template
slot-scope="{
items,
isShowingMore,
isFromSearch,
canToggleShowMore,
refine,
createURL,
toggleShowMore,
searchForItems,
}"
>
<div>
<UtilsFancyTitle
:text="filterType"
text-size="text-lg"
class="ml-4 my-4"
/>
<input
class="bg-white"
#input="searchForItems($event.currentTarget.value)"
/>
<ul class="flex flex-wrap">
<li v-if="isFromSearch && !items.length">No results ...</li>
<li v-for="item in items" :key="item.value" class="my-4 mr-4">
<a
:href="createURL(item)"
:class="
item.isRefined
? 'font-semibold bg-sm-yellow-primary border-sm-yellow-primary '
: 'font-medium'
"
class="
border-4 border-sm-black-primary
py-1.5
px-2
rounded-md
text-sm
"
#click.prevent="refine(item.value)"
>
<ais-highlight attribute="item" :hit="item" />
( {{ item.count.toLocaleString() }} )
</a>
</li>
</ul>
<div class="flex justify-center items-center">
<div class="w-1/4 h-1 bg-sm-black-primary rounded-md"></div>
<button
class="w-2/4 font-semibold my-6"
:disabled="!canToggleShowMore"
#click="toggleShowMore"
>
{{ !isShowingMore ? 'Show more' : 'Hide' }}
</button>
<div class="w-1/4 h-1 bg-sm-black-primary rounded-md"></div>
</div>
</div>
</template>
</ais-refinement-list>
</div>
</products-filter-section>
</ais-instant-search>
Script
import {
AisInstantSearch,
AisRefinementList,
AisInfiniteHits,
AisConfigure,
} from 'vue-instantsearch'
import algoliasearch from 'algoliasearch/lite'
import { mapGetters } from 'vuex'
export default {
components: {
AisInstantSearch,
AisRefinementList,
AisInfiniteHits,
AisConfigure,
},
data() {
return {
searchClient: algoliasearch(
'[API-ENDPOINT]',
'[API-KEY]'
),
filterTypes: [
'type',
'color',
],
searchParameters: {
filters: `category:${this.$route.path.split('/').pop()}`,
facetFilters: `type:someProductType`,
},
}
},
head() {
return {
link: [
{
rel: 'stylesheet',
href: 'https://cdn.jsdelivr.net/npm/instantsearch.css#7.4.5/themes/reset-min.css',
},
],
}
},
}
Is there any working solution for this?
The facets should be auto selected and in their refined state (for example: having their isRefined property set to rue) whenever the algolia query loads and the page renders.
This question has been posted a while ago, so you might already have found an answer, but I'll post mine anyway since I landed here after having the same issue.
In my case, at least, there were 2 problems:
I hadn't configured the "Attributes for faceting". This is explained in the docs and can be done easily via the admin or via API.
I was specifying the facets incorrectly in code. In your example above I think you should have:
searchParameters: {
facetFilters: [[`type:someProductType`]],
},
Note that now facetFilters is an array within an array.
What helps me when I'm unsure I open the admin UI of Algolia, select a search and apply whichever filter I want and then check the raw output. An example from my admin ui:
This gives me an idea of the correct shapes InstantSearch needs.

Manage undefined value of an object

I'm using Vue 3 and I want to show an image depending on the value of an object
So I have something like:
<img
v-if="results.object.value === 'test'"
src="#/assets/images/services/img.svg"
class="w-60"
alt=""
/>
<img
v-else-if="results.object.value === 'test2'"
src="#/assets/images/services/img2.svg"
class="w-80"
alt=""
/>
So this works correctly but sometimes the results.object.value is undefined and it throws an error in the console:
[Vue warn]: Error in render: "TypeError: Cannot read property 'value'
of undefined"
So I try to add another v-if to show other image if the value is undefined:
<img
v-else-if="!results.object.value"
src="#/assets/images/services/test3.svg"
class="w-40"
alt=""
/>
But I still get the same error. How can I manage it?
The problem is results.object is possibly undefined, so you should verify it exists before trying to access a subproperty. You could do this easily by wrapping both img elements with a <template v-if="results.object">. And you could show a fallback img, using an <img v-else>, adjacent to this template:
<template v-if="results.object">
<img
v-if="results.object.value === 'test'"
src="#/assets/images/services/img.svg"
class="w-60"
alt=""
/>
<img
v-else-if="results.object.value === 'test2'"
src="#/assets/images/services/img2.svg"
class="w-80"
alt=""
/>
</template>
<!-- show fallback img if no `results.object` -->
<img
v-else
src="#/assets/images/services/test3.svg"
class="w-80"
alt=""
/>
You can use optional chaining like:
results?.object?.value??'default'==='test'
or
just results?.object?.value === 'test'
<img
v-if="results?.object?.value === 'test'"
src="#/assets/images/services/img.svg"
class="w-60"
alt=""
/>
<img
v-else-if="results?.object?.value === 'test2'"
src="#/assets/images/services/img2.svg"
class="w-80"
alt=""
/>
<img
v-else-if="!results?.object?.value"
src="#/assets/images/services/test3.svg"
class="w-40"
alt=""
/>

Vue js passing HTML button name attribute as a PROPS

I created a custom component which contains an HTML button tag, so I'm using this component many times as a shared component into a parent component. I would like to know if I can pass the name attribute from the HTML button tag as a prop, so I can have a dynamically HTML button tag name attribute.
<div class="toggle">
<button
class="btn"
name="ships">
</div>
<script>
export default {
props: {
ships: {
type: String,
required: true,
default: ''
}
}
</script>
<toggle
:ships="white"
/>
<toggle
:ships="grey"
/>
<toggle
:ships="black"
/>
CODE
I've updated your fiddle: https://codesandbox.io/s/00yxy5lqzn
Things I've changed:
Toogle.vue
<button class="btn" v-bind:name="ships">BUTTON </button>
To change an HTML attribute just add an v-bind: in front of it, because you can not use mustaches there.
App.vue
<div id="app">
<toggle ships="black" />
<toggle ships="grey" />
<toggle ships="white"/>
</div>
Removed the double dot -> now the content of the property will be interpreted as an String.
Edit: Alternative you could do it this way (result is the same): <toggle :ships="'black'" /> <-- it's probably the better way
You can do this without using a prop by using inheritAttrs.
export default {
inheritAttrs: false,
name: "toggle",
};
And then use $attrs to access any fallthrough attributes e.g. name.
<div class="toggle">
<button class="btn"
v-bind:name="$attrs.name">BUTTON </button>
</div>
And then using your component would just be
<div id="app">
<toggle name="black" />
<toggle name="grey" />
<toggle name="white"/>
</div>