My question is if I am doing the below code correctly or is there a better way? I want to handle the change in any input values.
I have an object of options:
customOptions: {
1:"test 1",
2:"test 2",
3:"test 3",
}
and I am showing them in the template like this:
<div class="custom_options">
<div
class="row-fluid flex form-row"
v-for="(option, index) in customOptions"
:key="index"
>
<span>{{ index }}</span>
<span>
<input :value="option" :id="index" #change="handleChange" />
</span>
</div>
</div>
and finally my method:
handleChange(event) {
Vue.set(this.customOptions, event.target.id, event.target.value)
},
You could just use v-model like <input v-model="customOptions[index]"/> :
<div
class="row-fluid flex form-row"
v-for="(option, index) in customOptions"
:key="index"
>
<span>{{ index }}</span>
<span>
<input v-model="customOptions[index]"/>
</span>
</div>
Related
I am trying to get the outer loop's key inside the inner loops. Trying to get the radio button value with selected[item.key] but it doesn't work. It is possible to get the key of outer loop? or is that any better way to get the radio button value? The problem I encounter is that i was trying to get outer loop key as index of selected to store answer
<div v-for="(item,key) in items" :key="key">
<div> {{ item.title }}</div>
<div class="selections">
<div v-for="(selection,key) in item.selection" :key="key">
<input type="radio"
v-model="selected[item.key]
:name=item.name"
:value="selection.name">
<label :for="selection.name">{{selection.name}}</label
</div>
</div>
</div>
selected is an array ready to store those data.
item:[
{name:"item1",id:"1",selection:[
{id:1,name:"selection1"},
{id:2,name:"selection2"},
{id:3,name:"selection3"},
]
},
{name:"item2",id:"2",selection:[
{id:1,name:"selection1"},
{id:2,name:"selection2"},
{id:3,name:"selection3"},
]
},
{name:"item3",id:"3",selection:[
{id:1,name:"selection1"},
{id:2,name:"selection2"},
{id:3,name:"selection3"},
]
},
]
Try this:
<div v-for="item in items" :key="item.id">
<div> {{ item.title }}</div>
<div class="selections">
<div v-for="selection in item.selection" :key="selection.id">
<input type="radio"
v-model="selected.find(({ id }) => id === item.id).name"
:name="item.name"
:value="selection.name">
<label :for="selection.name">{{selection.name}}</label>
</div>
</div>
</div>
Or if you want to select the selection:
<div v-for="item in items" :key="item.id">
<div> {{ item.title }}</div>
<div class="selections">
<div v-for="selection in item.selection" :key="selection.id">
<input type="radio"
v-model="item.selection.find(({ id }) => id === selection.id).name"
:name="item.name"
:value="selection.name">
<label :for="selection.name">{{selection.name}}</label>
</div>
</div>
</div>
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>
how can i pass id of object vue js
I have a json file, from it I need to get the id of the selected option from the selector
<div class="select">
<div class="select-header form-control" v-on:click="AddForm(1)">
<span class="select__current" v-if="status_id == null">Please select status</span>
<span v-else>{{ typeStatus[status_id].name }}</span>
</div>
<div class=" select__body" v-if="addedForm === 1">
<div class="select-item" v-for="(type, index) in typeStatus" v-bind:key="type.id" v-on:click="status_id = index; addedForm = false;">
{{ type.name }}
</div>
</div>
</div>
methods: {
search() {
this.filter.append('status', this.typeStatus[this.status_id].id)
this.$emit('filter', this.filter);
},
}
My vue component like this :
<template>
<div class="panel panel-default">
<a #click="deleteAll" href="javascript:" class="btn btn-danger pull-right">
<span class="fa fa-trash"></span> Delete All
</a>
...
<tr v-for="item in list">
<td>
<div class="checkbox">
<label>
<input type="checkbox" :value="item.id" v-model="checkedData">
</label>
</div>
</td>
...
</tr>
...
</div>
</template>
<script>
export default {
data() {
return {
checkedData: []
}
},
methods: {
deleteAll() {
this.$http.post(window.BaseUrl+'/message/deleteAll', {ids: this.checkedData})
}
}
}
</script>
If I check the some checkbox and click delete all button, it will send value item.id by ajax
I want to send another value too. I have value item.seller_id and item.buyer_id
I try like this :
<input type="checkbox" :value="item._id+'#'+item.seller_id+'#'+item.buyer_id" v-model="checkedData">
So I use separator # to separate the value. Seems it works
Whether it is the best solution? Or is there another better solution?
Hi please look at this https://jsfiddle.net/p8zhrg6g/29/ .
<div v-for="item in list">
<input type="checkbox" :id="item.id" :value="item.value" v-model="checkedNames">
<label :for="item.id">{{item.value}}</label>
This is how I would have done it, hope this helps?
Just put value in array in :value..
<div v-for="item in list">
<input type="checkbox" :id="item.id" :value="[item.name, item.value]" v-model="checkedNames">
<label :for="item.id">{{item.value}}</label>
When you want call the value in another element, you can call value based on their value index like {{item[0]}} will display item.name and {{item[1]}} will display value.value
In my component Search.vue I need to detect whether search input focused or not in order to hide search results if cursor is elsewhere
I used vue-instantsearch
Here is the code of my custome component's template section
<template>
<ais-index index-name="getstarted_actors" :search-store="searchStore">
<div class="col-md-10 col-sm-9">
<ais-search-box :autofocus="true">
<div class="input-group" ref="searchInputGroup">
<ais-input placeholder="Find books..."
:class-names="{'ais-input': 'form-control'}" autofocus="true" >
</ais-input>
<span class="input-group-btn">
<ais-clear :class-names="{'ais-clear': 'btn btn-default'}">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</ais-clear>
<button class="btn btn-default" type="submit">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
</button>
</span>
</div>
</ais-search-box>
<ais-results v-show="searchStore.query.length > 0">
<template scope="{ result }">
<div v-on:click="searchResultClick(result)" class="found-item">
<a> <span>{{ result.name }}</span> <span>{{ result.rating }}</span></a><br/>
</div>
</template>
</ais-results>
</div>
</ais-index>
</template>
You can try:
<ais-input placeholder="Find books..."
:class-names="{'ais-input': 'form-control'}" autofocus="true"
#focus="onFocus"
>
</ais-input>
and your methods:
methods: {
onFocus() { console.log('Focused') }
}