how can i pass id of object vue js - vue.js

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);
},
}

Related

Nested Scoped Slots Variable Collisions VueJS

I've created a simple scoped slot component that I need to nest, but I'm struggling to figure out how I can avoid naming collisions.
Vue Component nested-fields
<script>
export default {
props: [
"entityName",
"items"
],
data: function() {
return {
formItems: this.items
}
},
methods: {
addItem: function() {
this.items.push({})
},
removeItem: function(index) {
if (this.items[index].id) {
this.$set(this.items[index], '_destroy', true);
} else {
this.items.splice(index, 1);
}
}
}
}
</script>
<template>
<div class="nested-fields">
<div v-show="item._destroy !== true || typeof item._destroy == 'undefined'" class="card nested-fields__field-set mb-2" v-for="(item, index) in formItems" :key="index">
<div class="card-header d-flex justify-content-between">
<span>Add {{entityName}}</span> <span class="fa fa-times" #click="removeItem(index)"></span>
</div>
<div class="card-body">
<slot name='item-fields' v-bind="{item, index}"></slot>
</div>
</div>
<button class="btn btn-primary btn-xs mb-2" type="button" #click="addItem()">Add {{entityName}}</button>
</div>
</template>
HTML
<nested-fields entity-name="Rotap Analysis" :items="[]">
<template #item-fields="{item, index}">
<div class="form-group col-sm-4">
<label>
Amount (g)
<input type="number" min="0" v-model="item.amount_grams" :name="'setup[input_material_attributes][rotap_analysis_attributes]['+index+'][amount_grams]'" class="form-control">
</label>
</div>
<div class="form-group col-sm-4">
</div>
<div class="form-group col-sm-4">
</div>
<nested-fields entity-name="Sieve" :items="[]">
<template #item-fields="{item2, index2}">
<label>
Sieve Size (US Mesh)
<input type="number" min="0" v-model="item2.size_mesh" :name="'setup[input_material_attributes][rotap_analysis_attributes]['+index+'][rotap_sieves]['+index2+'][size_mesh]'" class="form-control">
</label>
</template>
</nested-fields>
</template>
</nested-fields>
I need to rename the variables in the nested template shown here:
<nested-fields entity-name="Sieve" :items="item.rotap_sieves || []">
<!-- this line --><template #item-fields="{item2, index2}">
So I can use them here:
<input type="number" min="0" v-model="item2.size_mesh" :name="'setup[input_material_attributes][rotap_analysis_attributes]['+index+'][rotap_sieves]['+index2+'][size_mesh]'" class="form-control">
... BUT it does not let me rename the destructuring as I have it from "item" and "index" to "item2" and "index2".
For what it's worth, I'm attempting to replace Cocoon rails gem for nesting forms in my Rails app, though that shouldn't really matter.
Question - How can I rename the variables in nested scoped slots to avoid variable collisions?
I figured out it's a simple destructuring syntax solution:
<template #item-fields="{item: item2, index: index2}">
Works perfectly as expected!

Set Index in computed function

I have a v-for loop like following:
<div class="inputArea mt-2" v-for="(id, index) in inputs" :key="index">
<div class="row">
<div class="col-md-6 m-1">
<div class="mt-2">Input Number</div>
<b-form-input type="number" v-model="Number[index]"></b-form-input>
</div>
<div class="row">
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">Autofill 1</div>
<b-form-input type="text" :value="Autofill[index].autofill1" </b-form-input>
</div>
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">Autofill 2</div>
<b-form-input type="text" :value="Autofill[index].autofill2" </b-form-input>
</div>
</div>
</div>
</div>
How can I reference my index into a computed function:
computed: {
Autofill() { <!-- Autofill[index]() is not working -->
var returnelement = {};
if(this.json!= undefined) {
this.json.forEach(element => {
for(const item of this.Number) {
if (+element.number === +item)
returnelement = element;
}
});
}
return returnelement;
},
},
data() {
return {
inputs:[{}],
Number: [],
json: json, //imported before
}
}
Autofill[index] ( ) is not working, but I need this unique index in here..
Thanks for helping me out!
Try this
If you want to pass the index from the loop to Autofill, then you should use the methods.
You cannot pass data to a function from computed.
<div class="inputArea mt-2" v-for="(id, index) in inputs" :key="index">
<div class="row">
<div class="col-md-6 m-1">
<div class="mt-2">Number</div>
<b-form-input type="number" v-model="Number[index]"></b-form-input>
</div>
<div class="row">
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">Autofill 1</div>
<b-form-input type="text" :value="Autofill(index).autofill1" </b-form-input>
</div>
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">Autofill 2</div>
<b-form-input type="text" :value="Autofill(index).autofill2" </b-form-input>
</div>
</div>
</div>
</div>
<script>
export default {
//...
methods: {
Autofill(index) {
var returnelement = {};
if (this.json != undefined) {
this.json.forEach(element => {
for (const item of index) {
if (+element.number === +item)
returnelement = element;
}
});
}
return returnelement;
},
},
}
</script>

vuejs handle input change in loop

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>

VUEJS: Model not changing in for loop

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>

Append the search result in the input search field vue

Here i have an #click event
<h2 #click="action(customer.id)">{{ customer.name }}</h2>
When any result is clicked append this result to the input. Any ideas ?
<input class="search" type="text" name="search" v-model="search" placeholder="Search posts..."
#focus="magic_flag = true">
<div v-if="magic_flag">
<div class="post" v-for="customer in filteredCustomer">
<h2 #click="action(customer.id)">{{ customer.name }}</h2>
</div>
</div>
How can i append the clicked result from the search to the input?
js here updated:
methods: {
action(item) {
this.selected = item
this.search = item.name
this.magic_flag=false;
}
},
I display the rest of the content here updated:
<div v-if="selected">
<div class="post" v-for="customer in filteredCustomer">
<div v-if="customer === selected">
<h1>{{ customer.name }}</h1>
<h1>{{ customer.id }}</h1>
<h1>{{ customer.address }}</h1>
</div>
</div>
</div>
Instead of passing customer.id to the action method, you can pass customer object as parameter to action.
You can do something like this.
var vm = new Vue({
el: '#app',
data: {
search: "",
filteredCustomer:[{name:'test1',id:1},{name:'test2',id:2},{name:'test3',id:3}]
},
methods: {
action (customer) {
this.search=customer.name
this.filteredCustomer=this.filteredCustomer.filter(o=> o.id!=customer.id)
}
}
});
h2{cursor:pointer}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js" type="text/javascript"></script>
<div id="app">
<input class="search" type="text" name="search" v-model="search" placeholder="Search posts..."
>
<div >
<div class="post" v-for="customer in filteredCustomer">
<h2 href #click="action(customer)">{{ customer.name }}</h2>
</div>
</div>
</div>