Build v-for src image - vue.js

I'm doing a VUE 3 project and I have problems with v-for src image. I have the next code:
<template>
<div class="container">
<h2 class="title">Últimas incorporaciones</h2>
<div class="row">
<div
class="col-sm-6 col-md-4 col-lg-3"
v-for="pet in pets"
:key="pet.nombre"
>
<article class="card">
<div class="card-header">
<img
class="card-img-top"
v-bind:src="'../assets/pets/' + pet.imatge"
alt="Thor"
/>
</div>
<div class="card-body">
<div class="card-main">
<!-- <h3 class="card-title">{{ pet.nombre }}</h3> -->
<h3 class="card-title">{{ pet.nombre }}</h3>
<p class="card-text">{{ pet.ciudad }}</p>
</div>
<ul class="card-icons">
<li>
<img
class="card-icon"
src="../assets/icons/icon_cat.svg"
alt="Gato"
/>
</li>
<li>
<img
class="card-icon"
src="../assets/icons/icon_male.svg"
alt="Macho"
/>
</li>
</ul>
</div>
</article>
</div>
</div>
</div>
</template>
I want a v-for to show the images to each card. The pet.nombre and pet.ciudad is working good, but pet.image not.
My script is like this:
<script>
export default {
name: "PetList",
data() {
return {
pets: [
{
nombre: "Thor",
ciudad: "Barcelona",
imatge: "thor.png",
},
};
},
};
How can I show the images with this code?

You can use
<img class="card-img-top"
:src="`../assets/pets/${pet.image}`"
:alt="pet.nombre"
/>

Related

Header component is not registered first time properly

I want to showing profile on click for logged in user, when i click to that, my profile page is rendered, but header content is not loaded properly, i checked in console, it shown me an error, did you register component properly. but if i refresh or reload page, header content is showing and console error also cleared that showing did you register component properly.
please help me where i mistaken.
header.vue
<template>
<div>
<div class="top-header">
<div class="container">
<div class="row">
<div class="col-md-6">
<p>Free shipping on all orders over $100</p>
</div>
<div class="col-md-6">
<div class="links" v-if="!this.$page.auth.user">
<inertia-link :href="route('login.page')"> Log in </inertia-link>
<InertiaLink :href="route('RegistrationForm')">Register</InertiaLink>
</div>
<div class="id-link" v-else>
<div class="profile-content" #click="OpenProfile"> <b-link href="#"> Welcome {{this.$page.auth.user.name}} </b-link> </div>
<div class="profile" v-if="expanded">
<b-img src="/images/profile.jpg" alt="image"></b-img>
<ul>
<li> <b-button variant="primary"> <inertia-link :href="route('User-Profile')" method="get"> Profile </inertia-link> </b-button> </li>
<li> <b-button variant="primary"> <inertia-link :href="route('logout')" method="post"> Logout </inertia-link> </b-button> </li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<header>
<div class="container">
<div class="row">
<div class="col-md-3">
<div class="logo">
<img src="images/logo.png">
</div>
</div>
<div class="col-md-9">
<div class="navbar">
<ul>
<li> <InertiaLink :href="route('home')">Home</InertiaLink> </li>
<li>Fruits</li>
<li>Vegetables</li>
<li>Single</li>
<li> <inertia-link :href="route('Contact-Us')">Contact US</inertia-link> </li>
</ul>
</div>
</div>
</div>
</div>
</header>
</div>
</template>
<script>
import Dropdown from '#/Shared/Dropdown'
import Icon from '#/Shared/Icon'
import Profile from './Profile.vue'
export default {
components: {Dropdown,Icon,Profile},
data() {
return{
expanded:false,
profile:false,
}
},
methods:{
OpenProfile(){
if(this.expanded==false){
this.expanded=true;
}
else{
this.expanded=false;
}
},
}
}
</script>
profile.vue
<template>
<div class="contact-page">
<div>
<header-content> </header-content>
</div>
<div class="table-content">
<b-container>
<div class="table-heading">
<h1>User Profile</h1>
</div>
<b-row>
<b-col cols="3">
<div class="login-id">
<div class="id-img">
<b-img src="images/profile.jpg"></b-img>
</div>
<h2>{{this.$page.auth.user.name}}</h2>
</div>
</b-col>
<b-col cols="9">
<div class="table-area">
<div class="out-layer">
<div class="head">
<h4>User Information</h4>
</div>
<b-link>
<div class="pencil">
<b-img src="images/edit.png"></b-img>
</div>
</b-link>
</div>
<div class="user">
<b-row no-gutters>
<b-col cols="6"><span class="text">NAME</span></b-col>
<b-col cols="6"><span class="link">{{this.$page.auth.user.name}}</span></b-col>
</b-row>
</div>
</div>
</b-col>
</b-row>
</b-container>
</div>
<div>
<footer-content> </footer-content>
</div>
</div>
</template>
<script>
import HeaderContent from './Header.vue';
import FooterContent from './Footer.vue';
export default {
components: {HeaderContent,FooterContent},
data(){
return {
}
},
}
</script>
I see an error in profile.vue, you don't have to use this inside <template>.
Are other components you call in profile.vue registered correctly?
Try to remove some portions of code to debug which tags throw the error.

After obtaining more data the open panel is not correct

When loading the panels the first time and opening the panel in the third position. Everything is Ok.
When loading more elements, the panel that opens is not correct but it is still the one in the third position.
<div id="load-conversation">
<div class="row" style="margin-bottom: 10px;" v-show="referencesList.length >0">
<div class="col-md-12 text-center">
<button v-on:click="getEmails" class="btn btn-sm btn-blue">Cargar más</button>
</div>
</div>
<div class="panel panel-info" v-for="email in emails">
<!-- Head Panel-->
<div class="panel-heading" v-bind:class=" email.incoming ? 'white-inbox' : 'blue-reply'"
data-toggle="collapse" :href="`#collapse-new${email.id}`">
<!--Email Title-Button -->
<div class="row">
<div class="col-md-8">
<h5 v-if="email.incoming"><span class="fas fa-reply" aria-hidden="true"></span> ${email.sender_name}</h5>
<h5 v-else><span class="fas fa-share-square" aria-hidden="true"></span> ${email.sender_name}</h5>
</div>
</div>
</div>
<!--Body Panel-->
<div :id="`collapse-new${email.id}`" class="panel-collapse collapse">
<div class="panel-body">
<!--Email Head-->
<div class="container-fluid">
<div class="row">
<strong>SUBJECT: </strong><span class="text-info">${email.subject}</span></br>
<strong>FROM: </strong><span class="text-info">${email.sender_email}</span></br>
<strong>TO: </strong><span class="text-info"><span v-for="to in email.to">${to.email}, </span></span></br>
<strong>DATE: </strong><span class="text-info">${email.date}</span></br>
<strong v-if="email.cc.length > 0">CC: </strong><span class="text-info"><span v-for="cc in email.cc">${cc.email}, </span></span>
</div>
</div>
<br>
<!--Email Body-->
<div class="row container-fluid">
<div class="list-group-item"v-html="email.content_html">
</div>
<div>
<div class="bs-component">
<ul class="pager">
<li class="previous" data-toggle="collapse" :data-target="`#open-details-new${email.id}`">
<a href="javascript:void(0)">
<span class="glyphicon glyphicon-option-horizontal" aria-hidden="true"></span>
</a>
</li>
</ul>
</div>
<div :id="`open-details-new${email.id}`" class="collapse" v-html="email.complete_html">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
The important thing is to see that the new elements are placed in the order of the old elements, that is, the order is reversed in the list. By only adding the elements without changing the order everything works correctly.
<script>
var loadMore = new Vue({
el: '#load-conversation',
delimiters: ['${', '}'],
data: {
limit : 3,
referencesList : [1,2,3,4,5],
emails : [],
showLoadBtn: true,
},
mounted() {
this.getEmails()
},
methods: {
getEmails(){
axios.post("get_more_emails", { references: this.getReferences() })
.then(response => {
//console.log(response.data);
this.emails = [ ...response.data, ...this.emails ]
}).catch(function (error) {
console.log('error', error)
});
},
getReferences(){
...
}
},
})
</script>

How to call VueJS component from another component

I'm new to VueJS, i have different pages which i organized in 'components'. Now, different pages have different layouts, for example, some pages will not include the header and the footer (which are also individual components).
This is the code for a component that is supposed to include the header
<template>
<Header />
<div class="container main-content">
<div class="row">
<div class="col-lg-2"></div>
<div class="col-lg-8">
<h3 style="font-weight: bold;color: #000;">What will you like to do?</h3>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-6 dash-menu-item">
<div class="item-body">
<router-link to="/dashboards" class="">
<i class="fa fa-user fa-4x"></i>
<p>View Dashboards</p>
</router-link>
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-6 dash-menu-item">
<div class="item-body">
<router-link to="/home" class="">
<i class="fa fa-cogs fa-4x"></i>
<p>Manage Settings</p>
</router-link>
</div>
</div>
</div>
<div class="col-lg-2"></div>
</div>
</div>
</template>
<script>
import Header from './Header.vue'
export default{
name: 'Loyalty',
components:{
'Header': Header
}
}
</script>
And this is my Header.vue
<template>
<div>
<div class="head">
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
<span class="pull-left" style="padding-left: 10px;">
<router-link to="/home" class="header-text page-link"><span class="fa fa-arrow-left"></span> Home</router-link>
</span>
</div>
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6 custom-hidden-sm">
<span class="pull-right" style="padding-right: 10px;">
<span class="header-text">Waje Loyalty</span>
</span>
</div>
</div>
</div>
</div>
</template>
<script>
export default{
name: 'Header',
data(){
return{
page_name: this.$router.currentRoute.name
}
}
}
</script>
When i compile, i get the error:
- Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
How can i solve this?
The issue is caused by the two root elements in your Loyalty.vue template: <Header /> and <div class="container main-content">.
VueJS component templates can contain one and only one root node.
To solve this, wrap the content of your Loyalty.vue template with a root div.
<template>
<!-- root div -->
<div>
<Header />
<div class="container main-content">
<div class="row">
<div class="col-lg-2"></div>
<div class="col-lg-8">
<h3 style="font-weight: bold;color: #000;">What will you like to do?</h3>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-6 dash-menu-item">
<div class="item-body">
<router-link to="/dashboards" class="">
<i class="fa fa-user fa-4x"></i>
<p>View Dashboards</p>
</router-link>
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-6 dash-menu-item">
<div class="item-body">
<router-link to="/home" class="">
<i class="fa fa-cogs fa-4x"></i>
<p>Manage Settings</p>
</router-link>
</div>
</div>
</div>
<div class="col-lg-2"></div>
</div>
</div>
</div>
</template>

Template is not loading showing error [Vue warn]: Error compiling template:

I'm loading default listing using vuejs. When I browse page it show me following error
[Vue warn]: Error compiling template:
My html template is as bellow:
<template id="results-template">
<div class="results-wrap col-lg-8 col-md-8 ">
<h3>Results:</h3>
<div v-for="category in books" class="col-xs-3 col-sm-3 col-md-3 col-lg-3 pl-0">
<div class="single-vertical-book box">
<div class="book mt-20 text-center">
<img v-bind:src="{{category.URL}}" />
<div class="book-title-latest">
{{category.Title}}
</div>
<div class="book-author-lastest">
<a href="#" v-if="(category.Category == result.id)" v-for="(result,key) in genres" v-bind:key="result.id">
{{result.name}}
</a>
</div>
</div>
</div>
</div>
</div>
</template>
I'm using API to get data. When I inspected API response it's showing me response correctly but vuejs is not showing data in template. My VueJs code is as bellow:
Vue.component('Results',{
template : '#results-template',
props: ['books','genres']
})
and VueJs method is as bellow:
getBooks : function(){
var vm = this;
return $.get('apis.php?gtype=Books')
.done(function(d){
vm.books = JSON.parse(d);
});
}
My created on loading page code is as bellow:
created : function(){
var vm = this;
this.getBooks().done(function(){
........
});
}
Code for data :
data : {
books : []
}
Please help me what's wrong I'm doing?
Your are binding image incorrect way first of all make it correct. Replace your code:
<template id="results-template">
<div class="results-wrap col-lg-8 col-md-8 ">
<h3>Results:</h3>
<div v-for="category in books" class="col-xs-3 col-sm-3 col-md-3 col-lg-3 pl-0">
<div class="single-vertical-book box">
<div class="book mt-20 text-center">
<img :src="category.URL" />
<div class="book-title-latest">
{{category.Title}}
</div>
<div class="book-author-lastest">
<a href="#" v-if="(category.Category == result.id)" v-for="(result,key) in genres" v-bind:key="result.id">
{{result.name}}
</a>
</div>
</div>
</div>
</div>
</div>
</template>
with this code:
<template id="results-template">
<div class="results-wrap col-lg-8 col-md-8 ">
<h3>Results:</h3>
<div v-for="category in books" class="col-xs-3 col-sm-3 col-md-3 col-lg-3 pl-0">
<div class="single-vertical-book box">
<div class="book mt-20 text-center">
<img v-bind:src="{{category.URL}}" />
<div class="book-title-latest">
{{category.Title}}
</div>
<div class="book-author-lastest">
<a href="#" v-if="(category.Category == result.id)" v-for="(result,key) in genres" v-bind:key="result.id">
{{result.name}}
</a>
</div>
</div>
</div>
</div>
</div>
</template>
You've to use :src="category.URL" for image src binding not :src="{{category.URL}}"
Secondly in template call you are using "genres" have you initialized genres array or not? this may also cause for error. 1st check both of causes if problem not solved the check further.

How to add active class to specific element?

I have this methods :
methods: {
replyBox: function(e){
e.preventDefault();
this.isActive = !this.isActive;
);
},
In view i have this:
<div class="comment_list" v-for="comment in all_comments">
REPLY
<div id="reply-box-#{{comment.id}}" class="reply-box" v-bind:class="{active: isActive}">
<div class="user_comment row">
<div class="col-md-1 col-sm-1 col-xs-1">
<div class="user_profile_image {{ isset($current_user->personal_user) ? 'bg_blue' : 'bg_green'}}">
#if(isset($current_user->avatar) && $current_user->avatar != '')
<img src="{{ avatar_path($current_user->avatar)}}" alt="" />
#else
<img src="{{ home_asset('img/user_icon.png') }}" alt="" />
#endif
</div>
</div>
<div class="col-md-11 col-sm-11 col-xs-11">
<textarea class="comment_input" placeholder="Join the discussion..." #keydown.enter.prevent="postComment({{$current_user->id}}, {{$article->id}})" v-model.trim="reply_comment"></textarea>
</div>
</div>
</div>
</div>
Now what i want is to add class active only for element that is near reply link. In jquery i could use this and that find siblings but how can i do that in vue.js?
If you could add an additional property to the comment you could do the following:
Template:
<div class="comment_list" v-for="comment in all_comments">
REPLY
<div id="reply-box-#{{comment.id}}" class="reply-box" v-bind:class="{active: comment.isActive}">
<div class="user_comment row">
<div class="col-md-1 col-sm-1 col-xs-1">
<div class="user_profile_image {{ isset($current_user->personal_user) ? 'bg_blue' : 'bg_green'}}">
#if(isset($current_user->avatar) && $current_user->avatar != '')
<img src="{{ avatar_path($current_user->avatar)}}" alt="" />
#else
<img src="{{ home_asset('img/user_icon.png') }}" alt="" />
#endif
</div>
</div>
<div class="col-md-11 col-sm-11 col-xs-11">
<textarea class="comment_input" placeholder="Join the discussion..." #keydown.enter.prevent="postComment({{$current_user->id}}, {{$article->id}})" v-model.trim="reply_comment"></textarea>
</div>
</div>
</div>
</div>
Method:
methods: {
replyBox: function(comment) {
comment.isActive = !comment.isActive;
}
},
Alternatively, you can extract this in a separate component:
In a .vue file:
<template>
<li>
REPLY
<div id="reply-box-#{{comment.id}}" class="reply-box" v-bind:class="{active: comment.isActive}">
<div class="user_comment row">
<div class="col-md-1 col-sm-1 col-xs-1">
<div class="user_profile_image {{ isset($current_user->personal_user) ? 'bg_blue' : 'bg_green'}}">
#if(isset($current_user->avatar) && $current_user->avatar != '')
<img src="{{ avatar_path($current_user->avatar)}}" alt="" />
#else
<img src="{{ home_asset('img/user_icon.png') }}" alt="" />
#endif
</div>
</div>
<div class="col-md-11 col-sm-11 col-xs-11">
<textarea class="comment_input" placeholder="Join the discussion..." #keydown.enter.prevent="postComment({{$current_user->id}}, {{$article->id}})" v-model.trim="reply_comment"></textarea>
</div>
</div>
</div>
</li>
</template>
<script>
export default {
name: 'comment',
props: ['comment']
methods: {
replyBox: function(comment) {
comment.isActive = !comment.isActive;
}
},
};
</script>
Then you can use it like this:
<ul class="comment_list" v-for="comment in all_comments">
<comment :comment="comment"></comment>
</ul>
Straight from docs: https://v2.vuejs.org/v2/guide/class-and-style.html
<div v-bind:class="{ active: isActive }"></div>
isActive is your condition which has to be meet