Populate dependent dropdown from arrays only using AJAX Jquery - javascript

I'm trying to do a form with dropdown dependable options, the problem is that I can just use HTML, Javascript and Ajax, no database, so I have to fill the options directly with jquery, so far this is what I got, but is not working, any help would awesome, thank you :)
$(document).ready(function(){
var countries = [
{
"id": "1",
"name": "Mexico"
},
{
"id": "2",
"name": "USA"
},
{
"id": "3",
"name": "Canada"
}
]
var states = {
'mexico': [{
display: "Ciudad de Mexico",
value: "mx-city"
}, {
display: "Jalisco",
value: "jalisco"
}],
'usa': [{
display: "Texas",
value: "texas"
}, {
display: "Ohio",
value: "ohio"
}],
'canada': [{
display: "Montreal",
value: "montreal"
}, {
display: "Toronto",
value: "toronto"
}]
};
var states = {
'mx-city': [{
display: "Benito Juarez",
value: "benito-juarez"
}, {
display: "Cuauhtemoc",
value: "cuauhtemoc"
}],
'jalisco': [{
display: "Zapopan",
value: "zapopan"
}, {
display: "Guadalajara",
value: "Guadalajara"
}],
'texas': [{
display: "San Antonio",
value: "san-antonio"
}, {
display: "Austin",
value: "austin"
}],
'ohio': [{
display: "Colombus",
value: "colombus"
}, {
display: "Cleveland",
value: "cleveland"
}],
'montreal': [{
display: "Quebec",
value: "Quebec"
}, {
display: "Vermont",
value: "vermont"
}],
'toronto': [{
display: "Ontario",
value: "ontario"
}, {
display: "York",
value: "york"
}]
};
$("#country").on('click',function() {
var pais = $(this).val();
$("#country").find("option").remove();
$(countries).each(function (i) {
$("#country").append('<option id="'+countries[i].id+'">'+countries[i].name+"</option>");
});
console.log(pais);
});
function list(array_list){
$("#child_selection").html("");
$(array_list).each(function (i) {
$("#child_selection").append('<option value="'+array_list[i].value+'">'+array_list[i].display+"</option>");
});
}
$('#child_selection').change(function() {
var state = $(this).val();
if (states[state] == undefined) {
return $("#child").text('Selecciona tu ciudad');
}
list(states[state]);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script><form action="" method="" enctype="application/json">
<br/>Nombre: <input type="text" />
<br/>Edad: <input type="text" />
<br/>Pais:
<select name="country" id="country">
<option value="">Selecciona tu pais</option>
</select>
<br />Estado:
<select name="child_selection" id="child_selection">
<option value="">Selecciona tu estado</option>
</select>
<br/>Ciudad:
<select name="child" id="child">
<option value="">Selecciona tu ciudad</option>
</select>
<input type="submit" value="Submit" />
</form>

First of all you have 2 variables with the same name states and your code is not according to the format of your JSON. Below the code i have fixed. Have a look.
$(document).ready(function() {
var countries = [{
"id": "1",
"name": "Mexico"
}, {
"id": "2",
"name": "USA"
}, {
"id": "3",
"name": "Canada"
}]
var states = {
'mexico': [{
display: "Ciudad de Mexico",
value: "mx-city"
}, {
display: "Jalisco",
value: "jalisco"
}],
'usa': [{
display: "Texas",
value: "texas"
}, {
display: "Ohio",
value: "ohio"
}],
'canada': [{
display: "Montreal",
value: "montreal"
}, {
display: "Toronto",
value: "toronto"
}]
};
var cities = {
'mx-city': [{
display: "Benito Juarez",
value: "benito-juarez"
}, {
display: "Cuauhtemoc",
value: "cuauhtemoc"
}],
'jalisco': [{
display: "Zapopan",
value: "zapopan"
}, {
display: "Guadalajara",
value: "Guadalajara"
}],
'texas': [{
display: "San Antonio",
value: "san-antonio"
}, {
display: "Austin",
value: "austin"
}],
'ohio': [{
display: "Colombus",
value: "colombus"
}, {
display: "Cleveland",
value: "cleveland"
}],
'montreal': [{
display: "Quebec",
value: "Quebec"
}, {
display: "Vermont",
value: "vermont"
}],
'toronto': [{
display: "Ontario",
value: "ontario"
}, {
display: "York",
value: "york"
}]
};
$(countries).each(function(i) {
$("#country").append('<option id="' + countries[i].id + '">' + countries[i].name + "</option>");
});
$("#country").on('change', function() {
list(states[$("#country").val().toLowerCase()]);
});
function list(array_list) {
$("#child_selection").html("");
$(array_list).each(function(i) {
$("#child_selection").append('<option value="' + array_list[i].value + '">' + array_list[i].display + "</option>");
});
}
$('#child_selection').change(function() {
var state = $(this).val();
if (cities[state] == undefined) {
return $("#child").text('Selecciona tu ciudad');
}
array_list = cities[state.toLowerCase()];
$("#child").html("");
$(cities[state]).each(function(i) {
$("#child").append('<option value="' + array_list[i].value + '">' + array_list[i].display + "</option>");
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<br/>Nombre:
<input type="text" />
<br/>Edad:
<input type="text" />
<br/>Pais:
<select name="country" id="country">
<option value="">Selecciona tu pais</option>
</select>
<br />Estado:
<select name="child_selection" id="child_selection">
<option value="">Selecciona tu estado</option>
</select>
<br/>Ciudad:
<select name="child" id="child">
<option value="">Selecciona tu ciudad</option>
</select>
<input type="submit" value="Submit" />
</form>
Hope it helps :)

Related

How to use same JavaScript program multiple times on same website

I am working on my Portfolio project and for that I have made a International country code selector program for my phone number field. but the problem I'm facing right now is that I have two forms in my homepage one is Consultation Form and another one is Contact Form, and I want to use the same JS program for both Forms.
I don't want to rewrite the same type of program or functions again and again, because that negatively effects the performance of my website. but in the other hand I don't know how can I reuse the same code for two forms. It conflicts when I try to reuse the function.
I have a working dropdown menu for Contact Form, also I want to implement the same logic to Consultation Form by using the same program.
Please help me to figure out this problem.
// Cache the elements
const ccDiv = document.querySelector(".contact-frm-cc");
const ccButton = document.querySelector(".cc-telcode");
const ccContainer = document.querySelector(".cc-container");
const ccSearchInput = document.querySelector(".cc-search-box");
const ccList = document.querySelector(".cc-data-list");
var selectedCountry = ""; // saved by "code"
// Add event listeners to the button, input, and list
// We use a process called "event delegation" on the list
// to catch events from its children as they "bubble up" the DOM
// https://dmitripavlutin.com/javascript-event-delegation/
ccButton.addEventListener("click", handleButton);
ccSearchInput.addEventListener("input", handleInput);
ccList.addEventListener("click", handleListClick);
document.addEventListener("click", handleDocumentClick);
// All of the data held as objects within an array
const data = [
{ name: "Afganistan", code: "93", flag: "afg" },
{ name: "Albania", code: "355", flag: "alb" },
{ name: "Algeria", code: "213", flag: "dza" },
{ name: "American Samoa", code: "1-684", flag: "asm" },
{ name: "Andorra", code: "376", flag: "and" },
{ name: "Angola", code: "244", flag: "ago" },
{ name: "Anguilla", code: "1-264", flag: "aia" },
{ name: "Antarctica", code: "672", flag: "ata" },
{ name: "Antigua and Barbuda", code: "1-268", flag: "atg" },
{ name: "Argentina", code: "54", flag: "arg" },
{ name: "Armenia", code: "374", flag: "arm" },
{ name: "Aruba", code: "297", flag: "abw" },
{ name: "Australia", code: "61", flag: "aus" },
{ name: "Austria", code: "43", flag: "aut" },
{ name: "Azerbaijan", code: "994", flag: "aze" },
{ name: "Bahamas", code: "1-242", flag: "bhs" },
{ name: "Bahrain", code: "973", flag: "bhr" },
{ name: "Bangladesh", code: "880", flag: "bgd" },
{ name: "Barbados", code: "1-246", flag: "brb" },
{ name: "Belarus", code: "375", flag: "blr" },
{ name: "Belgium", code: "32", flag: "bel" },
{ name: "Belize", code: "501", flag: "blz" },
{ name: "Benin", code: "229", flag: "ben" },
{ name: "Bermuda", code: "1-441", flag: "bmu" },
{ name: "Bhutan", code: "975", flag: "btn" },
{ name: "Bolivia", code: "591", flag: "bol" },
{ name: "Bosnia and Herzegovina", code: "387", flag: "bih" },
{ name: "Botswana", code: "267", flag: "bwa" },
{ name: "Brazil", code: "55", flag: "bra" },
{ name: "British Indian Ocean Territory", code: "246", flag: "iot" },
{ name: "British Virgin Islands", code: "1-284", flag: "vgb" },
{ name: "Brunei", code: "673", flag: "brn" },
{ name: "Bulgaria", code: "359", flag: "bgr" },
{ name: "Burkina Faso", code: "226", flag: "bfa" },
{ name: "Burundi", code: "257", flag: "bdi" },
{ name: "Cambodia", code: "855", flag: "khm" },
{ name: "Cameroon", code: "237", flag: "cmr" },
{ name: "Canada", code: "1", flag: "can" },
{ name: "Cape Verde", code: "238", flag: "cpv" },
{ name: "Cayman Islands", code: "1-345", flag: "cym" },
{ name: "Central African Republic", code: "236", flag: "caf" },
{ name: "Chad", code: "235", flag: "tcd" },
{ name: "Chile", code: "56", flag: "chl" },
{ name: "China", code: "86", flag: "chn" },
{ name: "Christmas Island", code: "61", flag: "cxr" },
{ name: "Cocos Islands", code: "61", flag: "cck" },
{ name: "Colombia", code: "57", flag: "col" },
{ name: "Comoros", code: "269", flag: "com" },
{ name: "Cook Islands", code: "682", flag: "cok" },
{ name: "Costa Rica", code: "506", flag: "cri" },
{ name: "Croatia", code: "385", flag: "hrv" },
//------- MORE COUNTRIES TO ADD LATER
];
// Handles the document click - it checks to see if the clicked
// part of the document has a parent element which is either
// `null` or is the HTML element, and then closes the container
// if it's open
function handleDocumentClick(e) {
const { parentElement } = e.target;
document.addEventListener("click", (event) => {
if (!ccDiv.contains(event.target)) {
ccContainer.classList.remove("show-cc-list");
}
});
}
// Filters the data based on the characters
// at the start of the provided name
function filterData(data, value) {
return data.filter((obj) => {
return (
obj.name.toLowerCase().startsWith(value.toLowerCase()) ||
obj.code.toLowerCase().startsWith(value.toLowerCase())
);
});
}
// Create a series of list items based on the
// data passed to it
function createListHtml(data) {
return data.map((obj) => {
const { name, code, flag } = obj;
let isSelected = "";
if (obj.code == selectedCountry) isSelected = "selected-country";
return `
<li class="cc-list-items ${isSelected}" data-name="${name}" data-code="${code}" data-flag="${flag}">
<div class="flag-icon flag-icon-${flag}"></div>
<div class="name">${name} (+${code})</div>
</li>
`;
}).join("");
}
// Toggle the container on/off
function handleButton() {
ccContainer.classList.toggle("show-cc-list");
ccList.innerHTML = createListHtml(data);
}
// No data available list item
function createNoDataHtml() {
return '<li class="nodata">No data available</li>';
}
// When the input is changed filter the data
// according to the current value, and then
// create some list items using that filtered data
function handleInput(e) {
const { value } = e.target;
if (value) {
const filtered = filterData(data, value);
if (filtered.length) {
ccList.innerHTML = createListHtml(filtered);
} else {
ccList.innerHTML = createNoDataHtml();
}
} else {
ccList.innerHTML = createListHtml(data);
}
}
// Create some button HTML
function createButtonHtml(code, flag) {
return `
<div class="flag-icon flag-icon-${flag}"></div>
<option class="cc-code" value="+${code}">+${code}</option>
`;
}
// When an item is clicked, grab the relevant data
// attributes, create the new button HTML, and then
// close the container
function handleListClick(e) {
const item = e.target.closest("li") || e.target;
if (item.classList.contains("cc-list-items")) {
const { code, flag } = item.dataset;
selectedCountry = item.dataset.code;
ccButton.innerHTML = createButtonHtml(code, flag);
ccContainer.classList.remove("show-cc-list");
}
}
.cc-telcode {
margin-bottom: 1em;
display: flex;
justify-content: center;
width: 100%;
}
.cc-telcode div.cc-code,
.cc-list-items div.name {
margin-left: 0.25em;
}
.cc-container {
display: none;
width: 300px;
position: absolute;
}
.show-cc-list {
display: block;
z-index: +999;
}
.cc-data-list {
max-height: 100px;
list-style: none;
margin: 1em 0 0 0;
padding: 0;
overflow-y: scroll;
border: 1px soldi darkgray;
}
.cc-list-items {
display: flex;
padding: 0.25em;
border: 1px solid lightgray;
}
.cc-list-items:hover {
cursor: pointer;
background-color: lightyellow;
}
.selected-country {
cursor: pointer;
background-color: rgb(73, 118, 241);
}
.contact-frm-cc {
width:100px;
}
<link rel="stylesheet" href="https://amitdutta.co.in/flag/css/flag-icon.css">
<!------------- Working Dropdown Menu ------------>
<div class="contact-frm-cc">
<button class="cc-telcode">Tel code</button>
<section class="cc-container">
<input type="text" class="cc-search-box" placeholder="Search for country" />
<ul class="cc-data-list">
</ul>
</section>
</div>
<!------------- Not-Working Dropdown Menu ------------>
<!--
<div class="consult-frm-cc">
<button class="cc-telcode">Tel code</button>
<section class="cc-container">
<input type="text" class="cc-search-box" placeholder="Search for country" />
<ul class="cc-data-list">
</ul>
</section>
</div>
-->
You can create a function to register your form logic, and just pass your root form element.
here is a simple modification based on your code
<!-- https://codepen.io/DlmaK/pen/dyjXYrm -->

How to target array index position correctly in Vuejs?

HelloWorld.vue
<template>
<div>
<div v-for="(piza, index) in pizas" :key="piza.pname">
{{ piza.pname }}
<List
:content="matchpizza"
:pname="piza.pname"
:qname="quantitys[index] ? quantitys[index].qname : ''"
/>
</div>
</div>
</template>
<script>
import List from "./List.vue";
export default {
name: "HelloWorld",
components: {
List,
},
data() {
return {
pizas: [
{
pname: "chicken pizza",
},
{
pname: "chicken pizza spl",
},
{
pname: "mutton pizza",
},
{
pname: "plain pizza",
},
],
quantitys: [
{
qname: "one",
},
{
qname: "two",
},
{
qname: "three",
},
{
qname: "four",
},
{
qname: "five",
},
],
matchpizza: [
{
matchnum: "1",
availability: "later",
pname: "plain pizza",
qname: "five",
},
{
matchnum: "2",
availability: "buy now",
pname: "chicken pizza",
qname: "one",
},
{
matchnum: "3",
availability: "buy now",
pname: "plain pizza",
qname: "five",
},
{
matchnum: "4",
availability: "buy now",
pname: "chicken pizza spl",
qname: "five",
},
{
matchnum: "5",
availability: "later",
pname: "mutton pizza",
qname: "five",
},
],
};
},
};
</script>
List.vue
<template>
<div>
<div v-if="matchpizza.length > 0">
<div
v-for="match in matchpizza"
:key="match.matchnum"
:class="{
green: match.availability === 'buy now',
red: match.availability === 'later',
}"
>
<div v-for="quantity in quantitys" :key="quantity.qname">
{{ quantity.qname }}
</div>
<div class="next-data-two">{{ match.availability }}</div>
</div>
</div>
<div v-else class="next-data"><p>No availability</p></div>
</div>
</template>
<script>
export default {
components: {},
props: {
content: {
type: Array,
required: true,
},
pname: {
type: String,
required: true,
},
qname: {
type: String,
required: true,
},
},
data: function () {
return {};
},
methods: {},
computed: {
quantitys() {
return this.content.filter((a) => a.qname === this.qname);
},
matchpizza() {
return this.content.filter((a) => a.pname === this.pname);
},
},
};
</script>
<style scoped>
.next-data {
display: flex;
flex-direction: row-reverse;
margin-top: -2%;
margin-right: 40%;
color: blue;
}
.next-data-two {
display: flex;
flex-direction: row-reverse;
margin-top: -1%;
margin-right: 42%;
color: red;
margin-bottom: 1%;
}
</style>
See my working code here:-
https://codesandbox.io/s/data-display-tcr8oj?file=/src/components/HelloWorld.vue
From the helloworld.vue you can see this line :qname="quantitys[index] ? quantitys[index].qname : ''"
Where as per the above code, from the quantitys array. it is not pointing to the particular index value correctly?.
According to my output from codesandbox:-
For chicken pizza it showing as , chicken pizza --> one --> later
But correct path is, chicken pizza --> later --> five
Similarly for others too, having same issue....
Is it because of index position wrong or issue with logic??
As you mentioned your required pathe is chicken pizza --> later --> five.
This path doesnot have to do anything with the quantitys array. You could simply display the details using the content prop itself.
Working Fiddle https://codesandbox.io/s/data-display-forked-kjxuyv

Show alert on input change in vue js

How can i display a confirmation alert only if i want to change radio button on previous step? So if i confirm my action all steps below should be removed.
I've binded a #change directive to the radio button with a method implementing the expected confirmation alert, but it appears on each change i make.
Here is my fiddle
Thanks for your advices in advance
new Vue({
el: "#app",
data() {
return {
answer: ["1"],
stepsData: [
{
id: "1",
yes_section: "2",
no_section: "4",
name: "Step 1",
},
{
id: "2",
yes_section: "5",
no_section: "1",
name: "Step 2",
},
{
id: "3",
yes_section: "2",
no_section: "4",
name: "Step 3",
},
{
id: "4",
yes_section: "2",
no_section: "4",
name: "Step 4",
},
{
id: "5",
yes_section: "2",
no_section: "4",
name: "Step 5",
},
],
};
},
computed: {
quation() {
return this.answer.map((answer) => {
return this.stepsData.find((step) => step.id === answer);
});
},
},
methods: {
pushAnswer(answer) {
this.answer.push(answer);
},
confirmPopup() {
alert('Are you sure?')
},
},
});
.step {
background: #ccc;
padding: 20px;
margin-bottom: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(step, id) in quation" :key="id" class="step">
<div v-html="step.name"></div>
<div>
<input
type="radio"
:id="step.UF_NO_SECTION"
:name="step.ID"
:value="step.yes_section"
#click="pushAnswer(step.yes_section)"
#change="confirmPopup"
/>
<label
:for="step.UF_NO_SECTION"
class="legal-aid__step-btn button _outline _no"
>
YES {{ step.yes_section }}
</label>
</div>
<div class="legal-aid__step-action_no">
<input
type="radio"
:id="step.UF_NO_SECTION"
:name="step.ID"
:value="step.no_section"
#click="pushAnswer(step.no_section)"
#change="confirmPopup"
/>
<label
:for="step.UF_NO_SECTION"
class="legal-aid__step-btn button _outline _no"
>
NO {{ step.no_section }}
</label>
</div>
</div>
</div>
I would add a property on every stepData that is called isSelected which will be initialized to false and once it was clicked, it will be changed to true.
So you data will look like this:
stepsData: [
{
id: "1",
yes_section: "2",
no_section: "4",
name: "Step 1",
isSelected: false
},
....
]
You will need to change pushAnswer to set isSelected to `true:
#click="pushAnswer(step)"
pushAnswer(answer) {
answer.isSelected = true;
this.answer.push(answer.yes_section);
},
And confirmPopup function will check if the answer is already selcted or not:
#change="confirmPopup(step)"
confirmPopup(step) {
if (step.isSelected) {
alert('Are you sure?')
}
},
Of course you can change anything to your liking, but this is the basic idea

how to select multiple options from a search input with Jquery typeahead.js plugin

I am using jQuery Typeahead plugin. I have a search input and dropdown list containing different values as you see below
for example if I select the shipment report, I will see just the shipment data as you see below
I want to use the multiselect options instead of selecting just one value. I am following the demo example Hockey v2 . I have enable the multiselect in my script but it's still selecting just one value.
Any suggestions please what am I missing in my code ? Thank you.
var data = [{
"name": "country",
"id": "country",
"typeReport": "shipment"
}, {
"name": "customer name",
"id": "customer name",
"typeReport": "shipment"
}, {
"name": "order number",
"id": "order number",
"typeReport": "serial"
}, {
"name": "line number",
"id": "line number",
"typeReport": "serial"
}];
typeof $.typeahead === 'function' && $.typeahead({
input: ".js-typeahead-input",
minLength: 0,
maxItem: 8,
maxItemPerGroup: 6,
order: "asc",
hint: true,
searchOnFocus: true,
group: {
key: "typeReport",
template: function (item) {
var typeReport = item.typeReport;
return typeReport; } },
emptyTemplate: 'no result for {{query}}',
groupOrder: ["shipment", "serial"],
display: ["name"],
correlativeTemplate: true,
dropdownFilter: [{
key: 'typeReport',
template: '<strong>{{typeReport}}</strong> typeReport',
all: 'All Reports'
}],
multiselect: {
minLength: 1 },
template: '<span>' +
'<span class="name">{{name}}</span>' +
'</span>',
source: {
groupName: {
data: data
}
},
debug: true
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-typeahead/2.7.0/jquery.typeahead.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.11.1/typeahead.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-typeahead/2.7.0/jquery.typeahead.js"></script>
<form>
<div class="typeahead__container">
<div class="typeahead__field">
<span class="typeahead__query">
<input class="js-typeahead-input"
name="q"
type="search"
autofocus
autocomplete="on">
</span>
</div>
</div>
</form>
If you browse link as you mentioned "https://cdnjs.cloudflare.com/ajax/libs/jquery-typeahead/2.7.0/jquery.typeahead.js". There are no such type of attribute "multiselect".
It means that, you are using old version of type ahead script.
As per latest script "https://cdnjs.com/libraries/jquery-typeahead". Please see below are the example.
var data = [{
"name": "country",
"id": "country",
"typeReport": "shipment"
}, {
"name": "customer name",
"id": "customer name",
"typeReport": "shipment"
}, {
"name": "order number",
"id": "order number",
"typeReport": "serial"
}, {
"name": "line number",
"id": "line number",
"typeReport": "serial"
}];
typeof $.typeahead === 'function' && $.typeahead({
input: ".js-typeahead-input",
minLength: 0,
maxItem: 8,
maxItemPerGroup: 6,
order: "asc",
hint: true,
searchOnFocus: true,
group: {
key: "typeReport",
template: function(item) {
var typeReport = item.typeReport;
return typeReport;
}
},
emptyTemplate: 'no result for {{query}}',
groupOrder: ["shipment", "serial"],
display: ["name"],
correlativeTemplate: true,
dropdownFilter: [{
key: 'typeReport',
template: '<strong>{{typeReport}}</strong> typeReport',
all: 'All Reports'
}],
multiselect: {
limit: 5,
limitTemplate: 'You can\'t select more than 2 teams',
matchOn: ["id"],
data: function() {
var deferred = $.Deferred();
return deferred;
},
callback: {
onClick: function(node, item, event) {
event.preventDefault();
console.log(item);
alert(item.name + ' Clicked!');
},
onCancel: function(node, item, event) {
console.log(item)
}
}
},
template: '<span>' +
'<span class="name">{{name}}</span>' +
'</span>',
source: {
groupName: {
data: data
}
},
debug: true
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-typeahead/2.10.6/jquery.typeahead.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-typeahead/2.10.6/jquery.typeahead.js"></script>
<div class="typeahead__container">
<div class="typeahead__field">
<span class="typeahead__query">
<input class="js-typeahead-input"
name="q"
type="search"
autofocus
autocomplete="on">
</span>
</div>
</div>

Binding dropdown values using knockout js

I have the below JS:
function RowData(Township, Range, Section,Crop, Acres) {
var self = this;
self.Township = Township;
self.Range = Range;
self.Section = Section;
self.Crop = [{ value: "1", crop: "Irrigated Corn" }, { value: "2", crop: "Irrigated Sugar Beets" }, { value: "3", crop: "Irrigated Soybeans" }, { value: "4", crop: "Irrigated Sorghum (Milo, Sudan)" }, { value: "5", crop: "Irrigated Dry Edible Beans" }, { value: "6", crop: "Irrigated Potatoes" }, { value: "7", crop: "Irrigated Alfalfa" }, { value: "8", crop: "Irrigated Small Grains" }, { value: "9", crop: "Range/Pasture/Grass (Brome, Hay, CRP)" }, { value: "10", crop: "Urban Land" }, { value: "11", crop: "Open Water" }, { value: "12", crop: "Riparian Forest and Woodlands" }, { value: "13", crop: "Wetlands" }, { value: "14", crop: "Other Agricultural Lands (Farmsteads, Feedlots, etc.)" }, { value: "15", crop: "Irrigated Sunflower" }, { value: "16", crop: "Summer Fallow" }, { value: "17", crop: "Roads" }, { value: "18", crop: "Dryland Corn" }, { value: "19", crop: "Dryland Soybeans" }, { value: "20", crop: "Dryland Sorghum" }, { value: "21", crop: "Dryland Dry Edible Beans" }, { value: "22", crop: "Dryland Alfalfa" }, { value: "23", crop: "Dryland Small Grains" }, { value: "24", crop: "Dryland Sunflower" }, { value: "25", crop: "Dryland Sugar Beets" }, { value: "26", crop: "Dryland Potatoes" }, { value: "27", crop: "Irrigated Hay" }, { value: "28", crop: "Irrigated Rotation Pasture" }];
self.Acres = Acres;
}
function PBHEPViewModel() {
var self = this;
//Present Conditions
self.present_conditions = ko.observableArray([
new RowData()
]);
self.present_AddRow = function () {
self.present_conditions.push(new RowData())
}
self.present_RemoveRow = function (row) { self.present_conditions.remove(row) };
//Future Conditions
self.future_conditions = ko.observableArray([
new RowData()
]);
self.future_AddRow = function () {
self.future_conditions.push(new RowData())
}
self.future_RemoveRow = function (row) { self.future_conditions.remove(row) };
//submit the data
self.submit_conditions = function () {
var PC_data = ko.toJSON(self.present_conditions());
var FC_data = ko.toJSON(self.future_conditions());
$.post("/Home/PBHEP", { "PC": PC_data, "FC": FC_data});
}
}
ko.applyBindings(new PBHEPViewModel());
And my HTML is:
<tbody data-bind="foreach:future_conditions">
<tr>
<td style =" text-align:center">
<input class="input-small" type="text" placeholder="Township" data-bind="value: Township"></td>
<td style =" text-align:center">
<input class="input-small" type="text" placeholder="Range"data-bind="value: Range"></td>
<td style =" text-align:center">
<input class="input-small" type="text" placeholder="Section"data-bind="value: Section"></td>
<td style =" text-align:center">
<select name="" data-bind="options: Crop, optionsValue: 'value', optionsText: function (i) { return i.crop }, optionsCaption: 'Choose a Crop...'"></select>
</td>
<td style =" text-align:center">
<input class="input-small" type="text" placeholder="Acres"data-bind="value: Acres"></td>
<td>
<button class="btn btn-small btn btn-danger" type="button" data-bind="click: $root.future_RemoveRow"><i class="icon-minus-sign icon-white"></i></button>
</td>
</tr>
</tbody>
When I do the post I have all the entire array in the crop field where i only want to post the value that has been selected.
How do I achieve this where am I going wrong.
Thank you in advance
For a single-select list, you use the value binding to write the selected value to your viewmodel. See the note near the top of the documentation for details.
Try the below binding:
<select name="" data-bind="options: Crop, value: Crop, optionsText: 'crop', optionsCaption: 'Choose a Crop...'"></select>
This displays the text in the drop down as the crop property of your array items. It also assigns the selected value from the drop down to the Crop property of the RowData object.
You may want to change the name of the array, Crop, to Crops or something to differentiate it from the singular property on the RowData object. It is a little confusing, as is.

Categories