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
Related
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"
/>
I'm trying to get the value of my select but it isn't being picked up and I'm not sure why I've got v-model on my select tag and as far as I know it should have been picked up.
When I check my console I have a null.
Here is my code.
<template>
<div class="content-header">
<div class="container">
<div class="row">
<div class="col-sm-6">
<div class="card">
<div class="card-body">
<div class="row mb-2">
<div class="col-sm-12">
<label for="product_select">Products</label>
<select id="product_select" class="form-control" v-model="selectedValue">
<optgroup v-for="product in products" :label="product.text">
<option v-for="list in product.children" :value="list.id">{{ list.text }}</option>
</optgroup>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default{
props: ['products'],
data(){
return {
selectedValue: null
}
},
computed:{
},
watch: {
},
methods: {
}
mounted() {
console.log(this.selectedValue);
}
}
</script>
mounted is executed before your 'select' operation.
The V-model:"question.answer" is the same for each loop.
The content of rating_questions is:
rating_question = [
{
"id":1,
"question":"How did you like this?",
"amount_of_stars":8,
"answer":0
},
{
"id":2,
"question":"Second question?",
"amount_of_stars":3,
"answer":0
}]
When I select an answer for the first question, the answer is saved in rating_question[0].answer but if I select an answer for the second question, it is also saved in rating_question[0].answer and not in rating_questions[1].answer as I would expect.
<template>
<div class="ratings">
<div class="rating" v-for="(question, index) in rating_questions">
<div class="question">
{{ question.question }}
</div>
<div class="answer">
<div class="rating-stars">
<span v-for="i in question.amount_of_stars">
<input :id="i" name="rating" v-model="question.answer" type="radio" :value="i" class="radio-btn hide" />
<label :for="i" >☆</label>
</span>
{{ rating_questions[index]['answer'] }}
{{index}}
<div class="clear"></div>
</div>
</div>
</div>
<span class="input-group-btn">
<button class="btn btn-primary btn-sm" id="btn-chat" #click="sendRating">
Send
</button>
</span>
</div>
</template>
<script>
export default {
props: ['user', 'event', 'rating_questions'],
methods: {
sendRating() {
this.$emit('ratingsent', {
rating_questions: this.rating_questions
});
}
}
}
</script>
Your problem is not in Vue usage but how you use <input> and <label> HTML elements...
<input> id and <label> for attributes are assigned with simple number
1..question.amount_of_stars...which means first combo for every question will have id = 1, second 2 etc. Moreover you are using same name for every combo!
Now if you click on the label (star) in second question, browser just switch active combo on 1st question.
Try this:
<input :id="`rating-${question.id}-${i}`" :name="`rating-${question.id}`" v-model="question.answer" type="radio" :value="i" class="radio-btn hide" />
<label :for="`rating-${question.id}-${i}`" >☆</label>
Now:
every combo in the group (single question) will have same name (OK!)
every combo (and it's corresponding label) will have different id (OK!)
Also it's usually better to use :key together with v-for
new Vue({
data() {
return {
rating_questions: [
{
"id":1,
"question":"How did you like this?",
"amount_of_stars":8,
"answer":0
},
{
"id":2,
"question":"Second question?",
"amount_of_stars":3,
"answer":0
}]
}
}
}).$mount("#app")
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="ratings">
<div class="rating" v-for="(question, index) in rating_questions" :key="question.id">
<div class="question">
{{ question.question }}
</div>
<div class="answer">
<div class="rating-stars">
<span v-for="i in question.amount_of_stars">
<input :id="`rating-${question.id}-${i}`" :name="`rating-${question.id}`" v-model="question.answer" type="radio" :value="i" class="radio-btn hide" />
<label :for="`rating-${question.id}-${i}`" >☆</label>
</span>
{{ question.answer }}
<div class="clear"></div>
</div>
</div>
</div>
</div>
</div>
The error was in my input id's...
Each new question had the same id's.
<template>
<div class="ratings">
<div class="rating" v-for="(question, index) in rating_questions">
<div class="question">
{{ question.question }}
</div>
<div class="answer">
<div class="rating-stars">
<span v-for="i in question.amount_of_stars">
<input :id="'rating' + index + i" name="rating" v-model="question.answer" type="radio" :value="i" class="radio-btn hide" />
<label :for="'rating' + index + i" >☆</label>
</span>
<div class="clear"></div>
</div>
</div>
</div>
<span class="input-group-btn">
<button class="btn btn-primary btn-sm" id="btn-chat" #click="sendRating">
Send
</button>
</span>
</div>
</template>
<script>
export default {
props: ['user', 'event', 'rating_questions'],
methods: {
sendRating() {
this.$emit('ratingsent', {
rating_questions: this.rating_questions
});
}
}
}
</script>
There is very trivial fix of this problem.
See you are modifying the props. In vuejs, props are not supposed to be updated. I hope you might have encountered some error in the console (not sure though, as sometimes in my case also it doesn't appear)
Please use this SFC file
<template>
<div class="ratings">
<!-- using the data variable rather than props -->
<div class="rating" v-for="(question, index) in questions" :key="index">
<div class="question">
{{ question.question }}
</div>
<div class="answer">
<div class="rating-stars">
<span v-for="i in question.amount_of_stars" :key="i">
<input
:id="i"
name="rating"
v-model="question.answer"
type="radio"
:value="i"
class="radio-btn hide"
/>
<label :for="i">☆</label>
</span>
{{ questions[index]["answer"] }}
{{ index }}
<div class="clear"></div>
</div>
</div>
</div>
<span class="input-group-btn">
<button class="btn btn-primary btn-sm" id="btn-chat" #click="sendRating">
Send
</button>
</span>
</div>
</template>
<script>
export default {
props: ["user", "event", "rating_questions"],
data() {
return {
questions: this.rating_questions, // because you can not change props in vuejs
};
},
methods: {
sendRating() {
this.$emit("ratingsent", {
rating_questions: this.questions,
});
},
},
};
</script>
I am trying to create one component in VueJS and need to reuse that component.
below is code for me.
Vue.component("radio" , {
props: ['selectGender'],
data: function() {
return{
selected: 1
}
},
template : `
<div class="modal fade" :id="compId" style="background: rgb(0, 0, 0, 0.8);">
<div class="modal-dialog default-font" style="top: 30%;">
<div class="modal-content center">
<div class="modal-header base-bg center">
<div class="center">
<span class="validationHeadSpan">Select Gender</span><br/>
</div>
<button type="button" class="close modal-close" data-dismiss="modal" style="font-size:3rem">×</button>
</div>
<div class="modal-body t-left" id="printArea">
<div class="container">
<div class="row" style="padding: 0rem 1rem;">
<div class="col">
<div class="custom-control custom-radio" style="margin: 1rem 0rem;">
<input class="custom-control-input" type="radio" id="rdbMale" value="0" checked v-model="selected"/>
<label class="custom-control-label" for="rdbMale">
<div class="addr_header_1" style="margin-top: 0.8rem;">Male</div>
</label>
</div>
</div>
<div class="col">
<div class="custom-control custom-radio" style="margin: 1rem 0rem;">
<input class="custom-control-input" type="radio" id="rdbFemale" value="0" checked v-model="selected"/>
<label class="custom-control-label" for="rdbFemale">
<div class="addr_header_1" style="margin-top: 0.8rem;">Female</div>
</label>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer center">
<button type="button" class="button" data-dismiss="modal" v-on:click="selectGender(selected)"><span class="validationButtonContent">Select</span></button>
</div>
</div>
</div>
</div>
`,
mounted : function(){
},
methods : {
}
});
Here is my another component from where i am opening reusable component.
Vue.component("Component1" , {
data: function() {
return{
selected: 1
}
},
template : `
<div>
<radio ref="returnOpenFirst" :selectGender="selectGenderFirst"></radio>
<radio ref="returnOpenSecond" :selectGender="selectGenderSecond"></radio>
</div>
<div class="btn btn-primary formButton" v-on:click="openFirst">
<span>Open First</span>
</div>
<div class="btn btn-primary formButton" v-on:click="openSecond">
<span>Open First</span>
</div>
`,
mounted : function(){
},
methods : {
openFirst:function(){
jQuery(self.$refs.returnOpenFirst.$el).modal({
'backdrop' : false
}).modal('show');
},
openSecond:function(){
jQuery(self.$refs.returnOpenSecond.$el).modal({
'backdrop' : false
}).modal('show');
},
selectGenderFirst:function(gender){
console.log("First Gender", gender);
},
selectGenderSecond:function(gender){
console.log("Second Gender", gender);
},
}
});
While opening second component, data property is updated of first component only not for second component.
Any help is highly appreciated.
Thanks in advance.
Here i found solution.
Vue.component("radio" , {
props: ['selectGender','type'],
data: function() {
return{
selected: 1
}
},
template : `
<div class="modal fade" :id="compId" style="background: rgb(0, 0, 0, 0.8);">
<div class="modal-dialog default-font" style="top: 30%;">
<div class="modal-content center">
<div class="modal-header base-bg center">
<div class="center">
<span class="validationHeadSpan">Select Gender</span><br/>
</div>
<button type="button" class="close modal-close" data-dismiss="modal" style="font-size:3rem">×</button>
</div>
<div class="modal-body t-left" id="printArea">
<div class="container">
<div class="row" style="padding: 0rem 1rem;">
<div class="col">
<div class="custom-control custom-radio" style="margin: 1rem 0rem;">
<input class="custom-control-input" type="radio" :id="'rdbMale'+type" value="0" checked v-model="selected"/>
<label class="custom-control-label" :for="'rdbMale'+type">
<div class="addr_header_1" style="margin-top: 0.8rem;">Male</div>
</label>
</div>
</div>
<div class="col">
<div class="custom-control custom-radio" style="margin: 1rem 0rem;">
<input class="custom-control-input" type="radio" :id="'rdbFemale'+type" value="0" checked v-model="selected"/>
<label class="custom-control-label" :for="'rdbFemale'+type">
<div class="addr_header_1" style="margin-top: 0.8rem;">Female</div>
</label>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer center">
<button type="button" class="button" data-dismiss="modal" v-on:click="selectGender(selected)"><span class="validationButtonContent">Select</span></button>
</div>
</div>
</div>
</div>
`,
mounted : function(){
},
methods : {
}
});
Issue with same id created by VueJs, we need to pass one dynamic property and with the use of that we need to create id for radio.
Thank you guys.
I'm trying to change views on page load and on click events.
Here is what I have so far:
Vue.component('stale', {
template: '#stale-template'
});
Vue.component('buying', {
template: '#buying-template'
});
var vm = new Vue({
el: '.slot-container',
data: {
currentView: 'stale'
},
methods: {
buyTemplate: function(e) {
this.currentView = 'buying';
}
}
});
This is my HTML:
<div class="slot-container">
<component is="{{currentView}}"
v-transition="fade"
transition-mode="out-in">
</component>
</div><!-- END .SLOT-CONTAINER -->
<script id="stale-template" type="x-template">
STALE
<div class="slot stale">
<div class="row">
<div class="half">
<div class="buy-icon" v-on="click : buyTemplate">
<img src="{{ Asset.to('img/exchange/buy-icon.png') }}" alt="buy" />
<div class="title">Buy</div>
</div>
</div>
<div class="half">
<div class="sell-icon">
<img src="{{ Asset.to('img/exchange/sell-icon.png') }}" alt="sell" />
<div class="title">Sell</div>
</div>
</div>
</div>
</div>
</script>
<script id="buying-template" type="x-template">
BUYING
<div class="slot buying">
<div class="search">
<form action="{{ url_to('exchange/search') }}" method="post" id="buy-search" class="dark">
<input type="text" value="{{ input_old('item') }}" name="item" class="item-input" placeholder="Search item..." data-autocomplete="{{ url_to('search/item/autocomplete') }}" />
<button type="button" class="exchange-search-btn">Search</button>
</form>
</div>
<div class="results">
</div>
</div>
</script>
You can view the working example here: http://jsfiddle.net/4vgjx61t/
For some odd reason, I can never get anything to initiate to begin with. I'm following the example found here: http://vuejs.org/guide/application.html
Thank you.
You are using syntax valid in Vue 0.12 but are loading Vue 0.11 in the Fiddle. Add this as an external resource to fix it:
https://raw.githubusercontent.com/yyx990803/vue/dev/dist/vue.min.js