Display text of select option with button jQuery - javascript

Hello guys i have a question here. So in this problem i can't display the text from selected option while i click order button. For the result i need the selected option i choose and display it into a div. Any suggestion what i must change or add here?
P.S : Sorry i'm still learning here, i hope my question didn't confuse anyone here..
html
<div class="container">
<div class="container-fluid text-center">
<h2 style="font-size:70px; font-family:Lucida Console;">MENU</h2>
<br />
<div class="row">
<div class="col-md-6">
<select class="form-select form-select-lg mb-3" id="category_select" onChange='handleChange()'>
<option value="Food">Food</option>
<option value="Drink">Drink</option>
</select>
</div>
<br />
<div class="col-md-6">
<select class="form-select form-select-lg mb-3" id="type_select"></select>
</div>
</div>
</div>
</div>
<br />
<button type="button" style="width:50%; margin-left:25%; margin-right:25%">Order</button>
<br />
<div class="result"></div>
js
var data = {
Food: [
{
id: 1,
name: 'Fried Rice',
price: '10.000'
},
{
id: 2,
name: 'Fried Noodle',
price: '9.000'
},
{
id: 3,
name: 'Pancake',
price: '8.500'
},
{
id: 4,
name: 'French Fries',
price: '7.500'
}
],
Drink: [
{
id: 1,
name: 'Cola',
price: '4.600'
},
{
id: 2,
name: 'Orange Juice',
price: '5.400'
},
{
id: 3,
name: 'Mineral Water',
price: '3.500'
},
{
id: 4,
name: 'Coffee',
price: '5.800'
}
]
}
function handleChange() {
var x = document.getElementById("category_select").value;
var dataOptions = data[x]
var dataSelect = document.getElementById('type_select')
dataSelect.innerHTML = ''
dataOptions.forEach(function (option) {
var optionEle = document.createElement('option')
optionEle.value = option.id
optionEle.label = option.name
dataSelect.appendChild(optionEle)
})
}
handleChange()
$(document).ready(function () {
$("button").click(function () {
var selectMenu = [];
$.each($("#type_select"), function () {
selectMenu.push($(this)).val();
});
$(".result").html(selectMenu);
});
});

You should declare the array outside the click handler function. Also , you probably want to store the label attribute of the selected option. Join the array items with , before showing in the element:
var data = {
Food: [
{
id: 1,
name: 'Fried Rice',
price: '10.000'
},
{
id: 2,
name: 'Fried Noodle',
price: '9.000'
},
{
id: 3,
name: 'Pancake',
price: '8.500'
},
{
id: 4,
name: 'French Fries',
price: '7.500'
}
],
Drink: [
{
id: 1,
name: 'Cola',
price: '4.600'
},
{
id: 2,
name: 'Orange Juice',
price: '5.400'
},
{
id: 3,
name: 'Mineral Water',
price: '3.500'
},
{
id: 4,
name: 'Coffee',
price: '5.800'
}
]
}
function handleChange() {
var x = document.getElementById("category_select").value;
var dataOptions = data[x]
var dataSelect = document.getElementById('type_select')
dataSelect.innerHTML = ''
dataOptions.forEach(function (option) {
var optionEle = document.createElement('option')
optionEle.value = option.id
optionEle.label = option.name
dataSelect.appendChild(optionEle)
})
}
handleChange()
$(document).ready(function () {
var selectMenu = [];
$("button").click(function () {
selectMenu.push($("#type_select option:selected").attr('label'));
$(".result").html(selectMenu.join(', '));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="container-fluid text-center">
<h2 style="font-size:70px; font-family:Lucida Console;">MENU</h2>
<br />
<div class="row">
<div class="col-md-6">
<select class="form-select form-select-lg mb-3" id="category_select" onChange='handleChange()'>
<option value="Food">Food</option>
<option value="Drink">Drink</option>
</select>
</div>
<br />
<div class="col-md-6">
<select class="form-select form-select-lg mb-3" id="type_select"></select>
</div>
</div>
</div>
</div>
<br />
<button type="button" style="width:50%; margin-left:25%; margin-right:25%">Order</button>
<br />
<div class="result"></div>

To do what you require you can get the text() from the selected option in the type_select element.
Also note that there's a few optimisations you can make to your code. Firstly, as you're using jQuery already you can use it to bind the event handler to the change of the #category_select element unobtrusively, which is better practice than using onX event attributes. Also, you can use map() and html() to create the option elements to be added to the DOM more succinctly.
In addition, note that I removed the each() loop over the #type_select as only a single value can be selected from it, so the loop is redundant.
With that said, try this:
var data = {Food:[{id:1,name:"Fried Rice",price:"10.000"},{id:2,name:"Fried Noodle",price:"9.000"},{id:3,name:"Pancake",price:"8.500"},{id:4,name:"French Fries",price:"7.500"}],Drink:[{id:1,name:"Cola",price:"4.600"},{id:2,name:"Orange Juice",price:"5.400"},{id:3,name:"Mineral Water",price:"3.500"},{id:4,name:"Coffee",price:"5.800"}]};
jQuery($ => {
let $category = $('#category_select');
let $type = $('#type_select');
$category.on('change', e => {
let options = data[e.target.value].map(o => `<option value="${o.id}">${o.name}</option>`);
$type.html(options);
}).trigger('change');
$("button").click(function() {
$(".result").html(`${$type.find('option:selected').text()}: ${$type.val()}`);
});
});
button {
width: 50%;
margin-left: 25%;
margin-right: 25%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Irrelevant HTML removed from this example -->
<select class="form-select form-select-lg mb-3" id="category_select">
<option value="Food">Food</option>
<option value="Drink">Drink</option>
</select>
<select class="form-select form-select-lg mb-3" id="type_select"></select>
<button type="button">Order</button><br />
<div class="result"></div>

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>

Element deleted from the array but v-for doesn't update VUEJS

Guys so I'm trying to develop this rule component which can be spawned by my main component as many times as he wants but the problem is that when I delete an index from the list that tracks the number of rules, the vuejs layout doesn't update accordingly. What I mean by this is that if I check the array it self it deleted the correct item but when I look at the vue page (HTML) it either doesn't delete anything or only deletes the last item, and this may be caused by the v-for not updating on list change but I don't know how to solve this.
NewTask.vue (Parent)
<template>
<div class="mt-4">
<div class="container">
<div class="if-condition container-fluid d-flex flex-row ps-0">
<span class="text-center me-2 condition rounded">IF</span>
<select class="form-select form-select-sm me-2 if-select" v-model="if_condition">
<option value="ALL">ALL</option>
<option value="ANY">ANY</option>
<option value="NONE">NONE</option>
</select>
<span>of these filters match</span>
</div>
<div class="mt-2 ps-3 pt-3 pb-3 border">
<new-rule v-for="(item, index) in rules"
:key="JSON.stringify(index)" v-on:remove-rule="removeRule(index)"
:data="item" :index="index" v-on:data-changed="dataChanged"
class="mb-2"/>
<div class="mt-2 add-rule-div">
<button class="btn add-rule-btn" v-on:click="addRule">+</button>
</div>
</div>
</div>
</div>
</template>
<script>
import Rule from '#/components/rule'
export default {
name: "NewTask",
components: {
'new-rule': Rule
},
data: function () {
return {
if_condition: 'ALL',
rules: []
}
},
methods: {
dataChanged(data) {
const rules = this.rules;
const index = data.index;
delete data['index'];
rules.splice(index, 1, data)
this.rules = rules;
},
removeRule(index) {
const rules = this.rules;
rules.splice(index, 1)
this.rules = rules
},
addRule() {
const new_rule = {
type_input_text: null,
type_input_show: null,
rule_input_text: null,
rule_input_show: null,
}
this.rules.push(new_rule)
console.log(this.rules)
}
}
}
</script>
rule.vue (Child)
<template>
<div class="if-condition d-flex flex-row">
<select class="form-select form-select-sm me-2"
v-on:change="checkTypeSelect" v-model="type_select">
<option value="HTML">HTML</option>
<option value="XPATH">XPATH</option>
<option value="ID">ID</option>
<option value="CLASS">CLASS</option>
</select>
<input v-if="type_input_show" type="text" class="form-control me-2" v-model="type_input_text" v-on:change="dataChanged">
<select class="form-select form-select-sm me-2"
v-on:change="checkRuleSelect" v-model="rule_select">
<option value="CONTAINS">CONTAINS</option>
<option value="EXISTS">EXISTS</option>
</select>
<input v-if="rule_input_show" type="text" class="form-control me-2" v-model="rule_input_text" v-on:change="dataChanged">
<button class="btn remove-rule-btn pb-0 pt-0 ps-2 pe-2" v-on:click="this.$emit('remove-rule')">-</button>
</div>
</template>
<script>
export default {
name: "rule",
props: {
data: {
type: Object,
required: true
},
index: {
type: Number,
required: true
}
},
data: function () {
return {
type_select: 'HTML',
type_input_text: '',
rule_select: 'CONTAINS',
rule_input_text: '',
//
type_input_show: false,
rule_input_show: true,
}
},
beforeMount() {
if (this.data.type_select) {
this.type_select = this.data.type_select
this.checkTypeSelect()
}
if (this.data.type_input_text) {
this.type_input_text = this.data.type_input_text
}
if (this.data.rule_select) {
this.rule_select = this.data.rule_select
this.checkRuleSelect()
}
if (this.data.rule_input_text) {
this.rule_input_text = this.data.rule_input_text
}
},
methods: {
dataChanged() {
const new_data = {
index: this.index,
type_select: this.type_select,
type_input_text: this.type_input_text,
rule_select: this.rule_select,
rule_input_text: this.rule_input_text
}
this.$emit('data-changed', new_data)
},
checkTypeSelect() {
const type_select = this.type_select;
this.type_input_show = type_select !== 'HTML';
this.dataChanged()
},
checkRuleSelect() {
const rule_select = this.rule_select;
this.rule_input_show = rule_select !== 'EXISTS';
this.dataChanged()
}
}
}
</script>
Some images to demonstrate the issue:
Array Before Index delete:
Array After Index delete:
For further investigation feel free to visit the repo: https://github.com/DEADSEC-SECURITY/Easy-Scraper
THIS IS NOT PUBLICITY, I TRULY NEED HELP
You are using the index as a key. VueJS updates the DOM based on the change in key. So you have two options:
Use some distinct data from each entry or combination as a key.
Provide no key because as per Vuejs docs you need not provide a key anymore.

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>

dynamic item selection of product and price

I'm having a list of items in an array with its prices. The list of items must be displayed in a dropdown. When one is selected, I want its corresponding price to be placed into a text box called price.
JS:
function PopulateDropDownList() {
var products = [
{ productId: 1, name: "Fanta", price: "4" },
{ productId: 2, name: "Coke", price: "2" },
{ productId: 3, name: "Sprite", price: "8" },
{ productId: 4, name: "Malta Guniness", price: "10" }
];
}
HTML:
<body onload="PopulateDropDownList()">
<hr />
<select id="productsDropDown">
</select>
<input type="text" name="price" value="">
</body>
I think you are trying something like below-posted code.
function myFunction(e) {
document.getElementById("price").value = e.target.value
}
<hr />
<select id="productsDropDown" name="productsDropDown" onchange="myFunction(event)">
<option value="4">productId: 1</option>
<option value="2">productId: 2</option>
<option value="8">productId: 3</option>
<option value="10">productId: 4</option>
</select>
<input type="text" size="30" name="price" id="price" />
var demo = angular.module('demo', []);
function MyCtrl ($scope) {
$scope.myGroups = [
{label:'Admin', value:1},
{label:'Users', value:2},
{label:'Public', value:3}
];
$scope.tellUs = function() {
console.log("the selected group is - " + $scope.group);
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.6/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div ng-app='demo' ng-controller='MyCtrl'>
<p>You've just selected {{group}}.</p>
<form>
<select ng-model="group"
ng-options="o.value as o.label for o in myGroups"
ng-change="tellUs()"/>
</form>
</div>

V-for clicks all buttons instead of just one

I am new to Vue.js. I am trying to render check boxes from v-for (which renders correctly) based on an array.
Then I try to render a button beside each check box which opens a multi-select based on the selected index. But every time I click the rendered button, it opens up the multi select across all the checkbox buttons.
HTML:
<div>
<label class='label'>countrys:* </label><br><br>
<div
v-for="(country, index) in countries"
class="label"
style="display: inline-block;">
<input
type='checkbox'
value="country">&nbsp
{{country.geos}} &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp
<img
class='addIcon'
v-bind="country"
:key="country.index"
style="width: 26px;height: 20px;margin-right: 8px;margin-top: px;margin-left: -25px;margin-bottom:-5px"
src='../../images/createScreen/addClient#2x.png'
#click="makeMarketsActive($event, index)">
<select multiple v-if="!isHidden">
<option
v-for="(market) in country.markets"
v-bind="country">
{{ market }}
</option>
</select>
</div>
</div>
JS:
export default {
name: "Update",
components: {
},
data() {
return {
countries:[
{
"index":0,
"geos":"America",
"markets":['a','b','c','d']
},
{
"index":1,
"geos":"Canada",
"markets":['a','b']
},
"index":2,
"geos":"Africa",
"markets":['x','z']
}
],
isHidden:true
}
},
makeMarketsActive(event, index) {
this.isHidden = !this.isHidden;
}
Expected result : When clicking the image rendered for each checkbox I just want to see the market for each geo and not for all.
You also don't need the extra function
HTML
<div id="app">
<label class='label'>countries:* </label><br><br>
<div v-for="(country, index) in countries" class="label" style="display: inline-block;">
<input type='checkbox' value="country">{{country.geos}}
<img class='addIcon' v-bind="country" :key="country.index" style="margin-right: 8px;margin-top: px;margin-left: -25px;margin-bottom:-5px" src='https://via.placeholder.com/26x20' v-on:click="country.isVisible = !country.isVisible">
<select multiple v-show="country.isVisible">
<option v-for="(market) in country.markets" v-bind="country" >{{ market }}</option>
</select>
</div>
</div>
JS
new Vue({
el: '#app',
data: {
countries: [{
"index": 0,
"geos": "America",
"markets": ['a', 'b', 'c', 'd'],
"isVisible": false
},
{
"index": 1,
"geos": "Canada",
"markets": ['a', 'b'],
"isVisible": false
}, {
"index": 2,
"geos": "Africa",
"markets": ['x', 'z'],
"isVisible": false
}
]
}
})
First of all, as mentioned in comments, you are handling each button state via general property isHidden. So you need to add this property to data array:
new Vue({
el: "#app",
data: {
countries:[
{
"index":0,
"geos":"America",
"markets":['a','b','c','d'],
"isHidden":true
},
{
"index":1,
"geos":"Canada",
"markets":['a','b'],
"isHidden":true
},
{"index":2,
"geos":"Africa",
"markets":['x','z'],
"isHidden":true
}
]
},
methods: {
makeMarketsActive(event, index) {
this.countries[index].isHidden = !this.countries[index].isHidden;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<label class='label'>countrys:* </label><br><br>
<div v-for="(country, index) in countries" class="label" style="display: inline-block;">
<input type='checkbox' value="country">&nbsp{{country.geos}} &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp
<img class='addIcon' v-bind="country" :key="country.index" style="width: 26px;height: 20px;margin-right: 8px;margin-top: px;margin-left: -25px;margin-bottom:-5px" src='../../images/createScreen/addClient#2x.png' #click="makeMarketsActive($event, index)">
<select multiple v-if="!country.isHidden">
<option v-for="(market) in country.markets" v-bind="country" >
{{ market }}
</option>
</select>
</div>
</div>

Categories

Resources