Retrieve selected text from select - javascript

I'm using VueJS 2 (with this template) and below is what I've done so far:
<template>
<select id="dropDown" v-model="mytrack">
<option value="">Select track</option>
<option v-for="track in tracksList" :value="track.circuitId">{{ track.name }}</option>
</select>
<button type="submit" #click="retrieveByTrack(track.circuitId)">
Search
</button>
</template>
<script>
export default {
data() {
return {
tracksList: []
};
},
created: {
// here I fill tracksList[] with a list of tracks
},
methods: {
retrieveByTrack(trackId){
}
}
}
</script>
I want to be able to select an option from the select element and when I click the submit button I should call retrieveByTrack(track.circuitId) method passing the option value selected in the select element.

Simple like that.
I created fiddle for you:
https://jsfiddle.net/npw7fgta/
<div class='col-xs-12'>
<hr/>
<div id="app">
<pre>{{ $data |json }}</pre>
<select v-model='result'> <option v-for="task in tasks" :value="task.id">{{ task.name }} </option> </select>
</div>
</div>
And JS:
var vm = new Vue({
el: "#app",
data: {
tasks: [
{ id: 0 , name: 'First task'},
{ id: 5, name: 'fifth task'}
]
}
});
Then you have task/track.id available in result so you can do whatever you want.

Related

How to get an id of value in Vue.js

I am getting the data from API and I'm stuck with getting an id in order to send it back.
Example of data from API:
{
id:1,
name: 'qwerty',
},
{
id:2,
name: 'ytrewq',
},
API endpoint is expecting sending id via axios.post, not value, but v-model gets exactly the value.
<div class="form-group col-md-9">
<select class="form-select" id="inputSubject" v-model='subject'>
<option disabled value="">Select subject</option>
<option v-for="item in subjects" v-bind:value="item.name" :key="item.id">{{ item.name }}</option>
</select>
</div>
<div class="form-group col-md-9">
<select class="form-select" id="inputWorkType" v-model='work_type'>
<option disabled value="">Select work type</option>
<option v-for="item in work_types" v-bind:value="item.name" :key="item.id">{{item.name}}</option>
</select>
</div>
<script>
export default {
data () {
return {
subject: '',
work_type: '',
subjects: [],
work_types: [],
}
},
methods: {
// getting the data
getSubjectsWorkTypes() {
axios
.all([axios.get('/api/v1/subjects/'),
axios.get('/api/v1/worktypes/')
])
.then (
axios.spread((firstResponse, secondResponse) => {
console.log(firstResponse.data)
console.log(secondResponse.data)
this.subjects = firstResponse.data
this.work_types = secondResponse.data
}))
},
// sending the data
submitForm() {
console.log(this.subject.key())
const formData = {
subject: this.subject,
work_type: this.work_type,
}
axios
.post("api/v1/orders/", formData)
},
}
</script>
is there any smart way to get and send id? the only idea I have is to build the function which filters an array into finding id for the selected string...
the value of <select> is the selected <option>s value
You've set the value of the option to be the .name instead of the .id
const { ref, createApp, onMounted } = Vue;
createApp({
setup() {
const subject = ref("");
const subjects = ref([]);
const work_type = ref("");
const work_types = ref([]);
onMounted(() => {
// simulate API load
setTimeout(() => {
subjects.value = [
{ id: 1, name: 'qwerty', },
{ id: 2, name: 'ytrewq', },
];
work_types.value = [
{ id: 1, name: 'qwerty', },
{ id: 2, name: 'ytrewq', },
];
}, 1000);
});
return { subject, subjects, work_type, work_types, };
}
}).mount('#app');
#app {
display:flex;
justify-content: center;
gap:2rem;
}
.contain {
width:14rem;
}
.disp {
margin-bottom: 1rem;
}
.as-console-wrapper { max-height: 0 !important}
<script src="https://unpkg.com/vue#next"></script>
<div id="app">
<div class="contain">
This is wrong
<div class="disp">
Selected ID is {{ subject }}
</div>
<div>
<select class="form-select" id="inputSubject" v-model='subject'>
<option disabled value="">Select Work Type</option>
<option
v-for="item in subjects"
v-bind:value="item.name"
:key="item.id"
>
{{ item.name }}
</option>
</select>
</div>
</div>
<div class="contain">
This is right
<div class="disp">
Selected ID is {{ work_type }}
</div>
<div>
<select class="form-select" id="inputSubject" v-model='work_type'>
<option disabled value="">Select subject</option>
<option
v-for="item in work_types"
v-bind:value="item.id"
:key="item.id"
>
{{ item.name }}
</option>
</select>
</div>
</div>
</div>

How to sum selected values in option tag

So I have a v-for loop and 7 different documents from mongo database. Every document contains one food and for each food it has specific number of calories. And I want to sum all the selected calories. For example I got a variable food.calorie_number. Okay so I have something like this:
<tr>
<td v-for="(food) in fetch_breakfast.slice(8,15)" :key=food.id>Meal <p style="border-top: 3px solid #dddddd;">
<select class="form-select" aria-label="Default select example">
<option selected>Select your food</option>
<option v-bind:value="food.id">{{food.food}}</option>
<!-- Every meal has food.calorie_number -->
<option value="3"></option>
</select>
</p></td>
<p>Calorie sum: {{Sum}}</p>
</tr>
I wanted to do something like this: Sum = Sum + food.calorie_number but i didn't get the final solution because I don't know how to do it for a specific element generated by v-for.
If I understood you correctly try like following snippet (with computed and method for selection) :
new Vue({
el: '#demo',
data() {
return {
fetch_breakfast: [{id: 1, food: 'apple', calorie_number: 80}, {id: 2, food: 'peach', calorie_number: 70}, {id: 3, food: 'carrot', calorie_number: 90}],
selected: []
}
},
computed: {
sum() {
return this.selected.reduce((acc, curr) => acc + curr.calorie_number, 0)
}
},
methods: {
getSum(food) {
const idx = this.selected.findIndex(s => s.id === food.id)
idx > -1 ? this.selected.splice(idx, 1) : this.selected.push(food)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<table>
<tr>
<td v-for="food in fetch_breakfast" :key=food.id>Meal
<p>
<select class="form-select" #change="getSum(food)">
<option selected>Select your food</option>
<option :value="food.id">{{ food.food }}</option>
</select>
</p>
</td>
<p>Calorie sum: {{ sum }}</p>
</tr>
</table>
</div>
First you have v-for on the wrong element because that way it will return 7 select. if you want to have seven options put v-for in select but to have a default option that is not affected by the loop put in option like this:
then do your logic and fetch in either computed value
var selector = new Vue({
el: '#selector',
data: {
selected: null,
meals: [
{'id':1,
"name":"food_name_1",
"calories":"1.6g"
},
{'id':2,
"name":"food_name_g",
"calories":"1.8g"
},
{'id':3,
"name":"food_name_v",
"calories":"1.9g"
},
{'id':9,
"name":"food_name_v",
"calories":"1.66g"
},
{'id':11,
"name":"food_name_y",
"calories":"1.1g"
},
]
},
computed:{
selected_food(){
let id = this.selected
let selected_meal = this.meals.find(meal => meal.id === id)
return selected_meal
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="selector">
<select :default="0" v-model="selected">
<option selected="selected" :value=null>select meal</option>
<option v-for="(meal, key) in meals" :key=key :value="meal.id">
{{ meal.name }}
</option>
</select>
<br>
<br>
<div v-if="selected">
<span > Selected food : {{selected_food.name}}</span> </br>
<span > Selected food Calory : {{selected_food.calories}}</span>
</div>
<span v-else>Please select a meal</span>
</div>

Dynamically generate nested inputs in form

I'm very new into frontend, so I appreciate any help.
I'm trying to build a form, where user select an option from element and then depending on condition, dynamically generates another one (and some other inputs) as a child elements.
Finally what I'm trying to get is JSON with nested structure. E.g.
fields: [{type: 'List', value: [{type: 'Map', value: [{type: 'Integer', value: 5}, {type: 'List', value: [and so on...]]]}]
I have already started to code it in native JS and this is what I have so far (snippet below).
I want to release something similar with VUE.js library (or maybe someone can tell me any other useful libraries), cuz I want to control visibility of my inputs based on some conditions and some other useful features...but I dont know how to dynamically push elements into nested into nested and so on...I appriciate any help, any ideas and any examples. Thanks!
let template = `
<select name="type" onChange="createChildElement(this)" aria-label="Select type">
<option value="List">Select type</option>
<option value="List">List</option>
<option value="Map">Map</option>
<option value="Integer">Integer</option>
</select>
<select name="method" aria-label="Метод генерации">
<option value="Static">Static</option>
<option value="Random">Random</option>
<option value="Range">Range</option>
</select>
<input name="size" type="text" placeholder="Size">
<input name="value" type="text" placeholder="Value">
`;
function createChildElement(e) {
if(e.value == "List") {
var x = document.createElement('ul');
var z = document.createElement('li');
z.insertAdjacentHTML( 'beforeend', template );
x.appendChild(z);
e.parentNode.appendChild(x);
}
if(e.value == "Map") {
var x = document.createElement('ul');
var z = document.createElement('li');
z.insertAdjacentHTML( 'beforeend', template );
x.appendChild(z);
var y = document.createElement('ul');
var n = document.createElement('li');
n.insertAdjacentHTML( 'beforeend', template );
y.appendChild(n);
e.parentNode.appendChild(x);
e.parentNode.appendChild(y);
}
}
<body>
<div id="main-container">
<ul><li><div class="singleton-card ml-2">
<select name="type" onChange="createChildElement(this)" aria-label="Select type">
<option value="List">Select type</option>
<option value="List">List</option>
<option value="Map">Map</option>
<option value="Integer">Integer</option>
</select>
<select name="method" aria-label="Метод генерации">
<option value="Static">Static</option>
<option value="Random">Random</option>
<option value="Range">Range</option>
</select>
<input name="size" type="text" placeholder="Size">
<input name="value" type="text" placeholder="Value">
</div></li></ul>
</div>
</body>
I just found this example (https://codesandbox.io/s/github/vuejs/vuejs.org/tree/master/src/v2/examples/vue-20-tree-view?from-embed), I want to build something similar, but as a form with selects and inputs (just like my snippet example).
If I understand correctly, you're trying to create dependent dropdowns. You can check the following codepen for creating a dependent dropdown in vue.js
https://codepen.io/adnanshussain/pen/KqVxXL
JS
var model_options = {
1: [{ text: "Accord", id: 1 }, { text: "Civic", id: 2 }],
2: [{ text: "Corolla", id: 3 }, { text: "Hi Ace", id: 4 }],
3: [{ text: "Altima", id: 5 }, { text: "Zuke", id: 6 }],
4: [{ text: "Alto", id: 7 }, { text: "Swift", id: 8 }]
};
var makes_options = [
{ text: "Honda", id: 1 },
{ text: "Toyota", id: 2 },
{ text: "Nissan", id: 3 },
{ text: "Suzuki", id: 4 }
];
var vm_makes = new Vue({
el: "#app",
data: {
make: null,
model: null,
makes_options: makes_options,
model_options: model_options,
},
watch: {
make: function(event) {
$('#vehicle-models').dropdown('clear');
}
}
});
$('.ui.dropdown').dropdown();
HTML
<div id="app" class="ui grid">
<div class="row">
<div class="column">
<div class="ui label">Vechicle Make</div>
<select class="ui dropdown" v-model="make" id="vehicle-makes">
<option v-for="option in makes_options" v-bind:value="option.id">
{{ option.text }}
</option>
</select>
</div>
</div>
<div class="row">
<div class="column">
<div class="ui label">Vechicle Model</div>
<select class="ui dropdown" id="vehicle-models" v-model="model">
<option
v-for="option in model_options[make]"
:value="option.id"
:key="option.id"
>
{{ option.text }}
</option>
</select>
</div>
</div>
</div>

How to use v-model with multiple checkboxes generated by v-for?

Don't know how to use v-model on input checkbox type from a loop of a nested element.
I have successfully used a select/dropdown:
<select class="custom-select custom-select-sm" v-model="slide.filterCat">
<option :value="item.category" v-for="(item,index) in categories.elCats" :key="index">{{item.category}}</option>
</select>
It returns the item and models it correctly when updated,
however I would need to offer several options that can be selected and trying to use checkboxes instead.
The loop works fine and all labels and checkboxes are being shown correctly.
But I have no idea on how I can use simple v-model here.
I have used a method that checks if value is in array and if so to return true,
which works by using binding on :checked
:checked="isInCategoryList(item.category, slide.filterCat)
and the method:
isInCategoryList(curEl, list){
console.log(curEl);
console.log(list);
return list.includes(curEl ) ? true : false
},
But it logs an insane amount, which makes me think the approach is definitely not the correct one, for every event (mouseover,...) it keeps logging data.
And this snippet simply didn't work:
<div v-for="(item,index) in categories.elCats" :key="index">
<label>{{item.category}}</label>
<input type="checkbox" :value="item.category"
v-model="slide.filterCat">
</div>
Any guidance please...
Multiple checkboxes (as well as <select multiple>) requires the v-model argument to be an array...
const vm = new Vue({
el: '#app',
data() {
return {
selected: [],
categories: [{
name: 'Category A',
value: 'A'
},
{
name: 'Category B',
value: 'B'
},
{
name: 'Category C',
value: 'C'
},
]
}
}
})
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flexboxgrid/6.3.1/flexboxgrid.min.css" type="text/css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="row around-xs">
<div>
<h4>Checkboxes:</h4>
<div v-for="(item,index) in categories" :key="index">
<label>{{item.name}}</label>
<input type="checkbox" :value="item.value" v-model="selected">
</div>
</div>
<div>
<h4>Multi-select (using same model):</h4>
<select v-model="selected" multiple>
<option :value="item.value" v-for="(item,index) in categories" :key="index">{{item.name}}</option>
</select>
</div>
</div>
<h3>
Result: {{ selected }}
</h3>
</div>

Select multiple display names instead of IDs using AngularJS

I have a multiple select like this :
<select ng-model="listProds" multiple>
<option value="10">product 1</option>
<option value="25">product 2</option>
<option value="35">product 3</option>
<option value="48">product 4</option>
</select>
The values are the Ids for these products ( and this selectbox is generated using PHP )
& I've got this simple code in my app.js file :
var app = angular.module('myapp', []);
app.controller("PurchasesController", function($scope) {
// Init products Array
$scope.listProds = [];
});
When I display the listProds like this {{ listProds }}, I get an array containing the current selected items, but it only shows the Ids like this if I select all of them ["10","25","35","48"].
<fieldset ng-show="listProds.length > 0">
<div data-ng-repeat="p in listProds track by $index">
{{ p }} <!– Or –> {{ listProds[$index] }}
<input type="text" name="pr{{ listProds[$index] }}" />
<input type="text" name="qt{{ listProds[$index] }}" />
</div>
</fieldset>
This code generate two text boxes to enter the Price and Quantity for each Product in selected from the selectbox. So instead of using {{ p }} or {{ listProds[$index] }} and displaying the Product Id, I want to display there the Product name.
Thank you in advance.
You can create two lists: one for all your products and a separate list for the selected products:
$scope.listProds = [
{ key: 10, value: 'Product 1' },
{ key: 25, value: 'Product 2' },
{ key: 35, value: 'Product 3' },
{ key: 45, value: 'Product 4' }
];
$scope.selectedProds = [];
Now in your markup, instead of writing out each option in your select manually, you can use ng-options to generate your options. Using this approach, you are basically saying that each option is an object, and you want to use the objects value as the display name.
<select ng-model="selectedProds" ng-options="prod.value for prod in listProds" multiple>
Now your $scope.selectedProds array will contain the product objects, and not just they keys. So now you can display the name easily:
<fieldset ng-show="selectedProds.length > 0">
<div data-ng-repeat="p in selectedProds track by $index">
{{ p.value }}
<input type="text" name="pr{{ selectedProds[$index] }}" />
<input type="text" name="qt{{ selectedProds[$index] }}" />
</div>
</fieldset>
Not sure what your want the name attribute of the inputs to be, but I hope you get the idea.
Try this.
var app = angular.module('selTest', []);
app.controller('MainCtrl', function($scope) {
$scope.selectedProducts = [];
$scope.products = [
{ id:1, name: 'POne' },
{ id:2, name: 'PTwo' },
{ id:3, name: 'PThree' }
];
$scope.getNames = function(prods) {
return prods.map(function(p) {
return p.name;
});
};
$scope.getIds = function(prods) {
return prods.map(function(p) {
return p.id;
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="selTest">
<div ng-controller="MainCtrl">
<select name="products"
class="form-control input-sm"
ng-model="selectedProducts"
ng-options="p.name for p in products track by p.id"
ng-style="{'width':'100%'}" multiple>
</select>
<div>Selected Names: {{ getNames(selectedProducts) }}</div>
<div>Selected Ids: {{ getIds(selectedProducts) }}</div>
</div>
</div>

Categories

Resources