How to display multiple values from JavaScript array - javascript

my array has 2 elements. I'm creating a dynamic list using the "Name" and displaying the "Location" while submitting. But I also want to display the "ID" while submitting.
JS Code create a dynamic list using Name - ITC, JOY When I chose ITC, I want to display India and 100. But this code only allow me to choose single value from the array.
<!DOCTYPE html>
<html>
<body>
<head>
<script language="JavaScript">
var Comp = [
{Name: "ITC" , Location: "India ", ID: "100" },
{Name: "JOY" , Location: "US " ,ID: "200" },
];
var AllCustomers = document.getElementById("AllCustomers");
for (var i = 0; i < Comp.length; i++) {
var My_list = document.createElement("OPTION");
My_list.innerHTML = Comp[i].Name;
My_list.value = Comp[i].Location;
AllCustomers.appendChild(My_list)
}
function ShowCX()
{
document.getElementById("display_message").innerHTML=AllCustomers.value;
document.getElementById("display_message2").innerHTML=AllCustomers.value;
}
</script>
</head>
<select id="AllCustomers">
</select>
<input type="button" onclick="ShowCX()" value="submit" />
<p> Location: <span id = "display_message"></span> </p>
<p> ID: <span id = "display_message2"></span> </p>
</body>
</html>

I think this is what you're looking for. What I did is I stored an Object with the Location and ID in the value attribute and accessed it when it was selected. There are many ways to do this though. Also I changed the for loop for better abstraction.
var Comp = [{
Name: "ITC",
Location: "India ",
ID: "100"
},
{
Name: "JOY",
Location: "US ",
ID: "200"
},
];
var AllCustomers = document.getElementById("AllCustomers");
/*for (var i = 0; i < Comp.length; i++) {
var My_list = document.createElement("OPTION");
My_list.innerHTML = Comp[i].Name;
My_list.value = Comp[i].Location;
AllCustomers.appendChild(My_list)
}*/
Comp.forEach(element=>{
var My_list = document.createElement("OPTION");
My_list.innerHTML = element.Name;
My_list.value = JSON.stringify({"loc":element.Location,"id":element.ID});//storing as a JSON in value attribute
AllCustomers.appendChild(My_list)
})
function ShowCX() {
value = JSON.parse(AllCustomers.value); //gettinng the JSON
document.getElementById("display_message").innerHTML = value.loc;
document.getElementById("display_message2").innerHTML = value.id;
}
<!DOCTYPE html>
<html>
<body>
<head>
</head>
<select id="AllCustomers">
</select>
<input type="button" onclick="ShowCX()" value="submit" />
<p> Location: <span id="display_message"></span> </p>
<p> ID: <span id="display_message2"></span> </p>
</body>
</html>

You can get the selected index of the by using its selectedIndex property that way you can dynamically display your values based on user input. I've also added in the id.
<!DOCTYPE html>
<html>
<head></head>
<body>
<select id="AllCustomers"></select>
<input type="button" onclick="ShowCX()" value="submit" />
<p> Location: <span id="display_message"></span> </p>
<p> ID: <span id="display_message2"></span> </p>
<script language="JavaScript">
var Comp = [
{ Name: "ITC", Location: "India ", ID: "100" },
{ Name: "JOY", Location: "US ", ID: "200" },
];
var AllCustomers = document.getElementById("AllCustomers");
for (var i = 0; i < Comp.length; i++) {
var My_list = document.createElement("OPTION");
My_list.innerHTML = Comp[i].Name;
My_list.value = Comp[i].Location;
My_list.id = Comp[i].ID;
AllCustomers.appendChild(My_list)
}
function ShowCX() {
var selectedIndex = document.getElementById("AllCustomers").selectedIndex
document.getElementById("display_message").innerHTML = AllCustomers[selectedIndex].value; document.getElementById("display_message2").innerHTML = AllCustomers[selectedIndex].value;
document.getElementById("display_message2").innerHTML = AllCustomers[selectedIndex].value; document.getElementById("display_message2").innerHTML = AllCustomers[selectedIndex].id;
}
</script>
</body>
</html>

document.getElementById("display_message2").innerHTML=Comp[AllCustomers.selectedIndex].ID;

Related

Need to parse a Json object and append it to a table

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function myFunction() {
var abc, obj, i, j;
abc = {
"cars": [
'{"model":"Sentra", "doors":4, "lol":["hi","hello","hahahaha"]}',
'{"model":"Maxima", "doors":4,"lol":["hi","hello","hahahaha"]}',
'{"model":"Skyline", "doors":2,"lol":["hi","hello","hahahaha"]}'
]
}
var obj = JSON.parse(abc);
var theader = "<tr><th>Title</th><th>Author</th><th>year</th></tr>";
document.getElementById("dtable").appendChild(theader);
var x;
for (i = 0; i < abc.cars.length; i++) {
x += "<tr><td>" + obj.cars[i].model + "</td><td>" + obj.cars[i].doors + "</td><td>" + obj.cars[i].lol[0] + "</td></tr>";
document.getElementById("dtable").appendChild(x);
}
};
</script>
</head>
<body>
<div class="container" ,id="dsjson">
<button type="button" onclick="myFunction()">display json</button>
<br><br>
<table id="dtable"></table>
</div>
</body>
</html>
The nested json data needs to be displayed in the HTML table. On clicking the button the table displaying the json must appear. We can use JavaScript or JQuery For that one. In my example, I am using JavaScript. I don't know where it's going wrong.
you dont need to parse abc since it is already an object, but you need to parse each car object
<html>
<head>
<script type="text/javascript">
function myFunction(){
var abc,obj,i,j;
abc =
{"cars": [
' {"model":"Sentra", "doors":4, "lol":["hi","hello","hahahaha"]}',
'{"model":"Maxima", "doors":4,"lol":["hi","hello","hahahaha"]}',
'{"model":"Skyline", "doors":2,"lol":["hi","hello","hahahaha"]}'
]}
var obj = abc;
var theader = "<tr><th>Title</th><th>Author</th><th>year</th></tr>";
document.getElementById("dtable").appendChild(theader);
var x;
for (i=0; i < abc.cars.length; i++) {
abc.cars[i]=JSON.parse(abc.cars[i]);
x += "<tr><td>" + obj.cars[i].model + "</td><td>" + obj.cars[i].doors+ "</td><td>" + obj.cars[i].lol[0]+ "</td></tr>" ;
document.getElementById("dtable").appendChild(x);
}
};
</script>
</head>
<body>
<div class ="container" ,id = "dsjson">
<button type="button" onclick="myFunction()">display json</button>
<br><br>
<table id="dtable"></table>
</div>
</body>
</html>```
Your data is already an object. No need to parse it. The javascript interpreter has already parsed it for you.
If you want to add content using html strings, you can use insertAdjacentHTML in Vanilla.js
const dtable = document.getElementById("dtable");
const obj = {
"cars": [{
"model": "Sentra",
"doors": 4,
"lol": [
"hi",
"hello",
"hahahaha"
]
},
{
"model": "Maxima",
"doors": 4,
"lol": [
"hi",
"hello",
"hahahaha"
]
},
{
"model": "Skyline",
"doors": 2,
"lol": [
"hi",
"hello",
"hahahaha"
]
}
]
};
const cars = obj.cars;
const theader = "<tr><th>Title</th><th>Author</th><th>year</th></tr>";
function myFunction() {
for (let i = 0; i < cars.length; i++) {
if (i == 0) {
dtable.insertAdjacentHTML('beforeend', theader);
}
let row = `<tr>
<td>${cars[i].model}</td>
<td>${cars[i].doors}</td>
<td>${cars[i].lol[0]}</td>
</tr>`;
dtable.insertAdjacentHTML('beforeend', row);
}
};
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class="container" ,id="dsjson">
<button type="button" onclick="myFunction()">display json</button>
<br><br>
<table id="dtable"></table>
</div>
</body>
</html>
You have few issues in your code.
First of all appendChild() accepts a dom node as the parameter but you are providing htmlString, try insertAdjacentHTML() OR innerHTML instead.
Then you are modifying the DOM inside the loop with the previous value, this will duplicate the result.
You can try the following way:
function myFunction(){
var abc,i,j;
var abc = {
"cars": [
{"model":"Sentra", "doors":4, "lol":["hi","hello","hahahaha"]},
{"model":"Maxima", "doors":4,"lol":["hi","hello","hahahaha"]},
{"model":"Skyline", "doors":2,"lol":["hi","hello","hahahaha"]}
]
};
var theader = "<tr><th>Title</th><th>Author</th><th>year</th></tr>";
document.getElementById("dtable").innerHTML = theader;
var x ='';
for (i=0; i < abc.cars.length; i++) {
x += "<tr><td>" + abc.cars[i].model + "</td><td>" + abc.cars[i].doors+ "</td><td>" + abc.cars[i].lol[0]+ "</td></tr>";
}
document.getElementById("dtable").innerHTML += x;
};
<div class ="container" id = "dsjson">
<button type="button" onclick="myFunction()">display json</button>
<br><br>
<table id="dtable"></table>
</div>
Use some JSON validator tools like https://jsonlint.com/ or similar.
Now no need for abc var.
var obj = {
cars: [
{
model: "Sentra",
doors: 4,
lol: ["hi", "hello", "hahahaha"]
},
{
model: "Maxima",
doors: 4,
lol: ["hi", "hello", "hahahaha"]
},
{
model: "Skyline",
doors: 2,
lol: ["hi", "hello", "hahahaha"]
}
]
};
I think you are a bit confused with appendChild and innerHTML.
If you want to use appendChild you will need to provide an HTML element, however, if you just want to add HTML text, use innerHTML.
abc is already a JSON object, so you don't need to parse it again, however, you will want to parse the lol prop inside.
Here are those changes and some small improvements, using object destructuring to clean some things up a little.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function myFunction() {
var abc, obj, i, j;
abc = {
"cars": [
'{"model":"Sentra", "doors":4, "lol":["hi","hello","hahahaha"]}',
'{"model":"Maxima", "doors":4,"lol":["hi","hello","hahahaha"]}',
'{"model":"Skyline", "doors":2,"lol":["hi","hello","hahahaha"]}'
]
}
var theader = "<tr><th>Title</th><th>Author</th><th>year</th></tr>";
document.getElementById("dtable").innerHTML = (theader);
var x = "";
for (i = 0; i < abc.cars.length; i++) {
const car = JSON.parse(abc.cars[i])
const { model, doors, lol } = car
x += "<tr><td>" + model + "</td><td>" + doors + "</td><td>" + lol[0] + "</td></tr>";
}
document.getElementById("dtable").innerHTML += x;
};
</script>
</head>
<body>
<div class="container" ,id="dsjson">
<button type="button" onclick="myFunction()">display json</button>
<br><br>
<table id="dtable"></table>
</div>
</body>
</html>

Unable to retrieve data objects from my JSON file

I've created a JSON file to call out the name of a list of beers to display ABV and country but I am unable to display the results on the webpage. I was able to get the select tag to drop down the list, but when selecting a beer, it will only show the selected results as "undefined."
Here is the JS code I have so far...
var $select = $("#beerListing");
var beer = Array();
var country = Array();
$.getJSON("data.json", function(data) {
$select.html('');
for (var i = 0; i < data['beer'].length; i++)
$select.append('<option id="' + data["beer"][i]['id'] + '">' + data["beer"][i]["beer_name"] + '</option>');
for (x in data) {
if (beer.indexOf(data[x].beer_name) < 0) {
var y = beer.length;
beer[y] = data[x].beer_name;
country[y] = data[x].brewery_country;
}
}
showBeerList();
});
function showBeerList() {
var select = document.getElementById('beerListing');
for (var i = 0; i < beer.length; i++) {
var obj = document.createElement("option");
obj.text = beer[i];
obj.value = i;
select.appendChild(obj);
}
}
function getBeerInfo(picked) {
if (picked == "Pick Your Poison...") {
location.reload();
} else {
document.getElementById("name").innerHTML = beer[picked];
document.getElementById("country").innerHTML = country[picked];
}
}
HTML:
<html>
<head></head>
<body>
<h1>LCBO API TESTING</h1>
<select name="beerlist" id="beerListing" class="form-control" onchange="getBeerInfo(this.value)">
</select>
<br>
<label>Name:</label>
<label id="name">--</label>
<br>
<label>Country:</label>
<label id="country">--</label>
<br>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="main.js"></script>
</body>
</html>
JSON List called data.json
{
"beer": [{
"beer_name": "Organic Devon Cider",
"brewery_name": "Luscombe Organic Drinks",
"beer_type": "Cider",
"beer_abv": "4.9",
"beer_ibu": "0",
"comment": "",
"venue_name": "The Anchor & Hope",
"venue_city": "London",
"venue_state": "Greater London",
"brewery_country": "England"
}, {
"beer_name": "Beer A",
"brewery_name": "Beer A",
"beer_type": "Cider",
"beer_abv": "4.9",
"beer_ibu": "0",
"comment": "",
"venue_name": "Beer",
"venue_city": "New York",
"venue_state": "New York",
"brewery_country": "USA"
}]
}
You seemed to be adding the options to the select element twice and using for-in which iterates properties, not entries in an array.
Below snippet will not work as requires external data source.
var $select = $("#beerListing") ;
var beer = Array();
var country = Array();
$.getJSON("data.json", function(data) {
$select.html('');
for (var i = 0; i < data.beer.length; i = i + 1) {
if (beer.indexOf(data.beer[i].beer_name) < 0) {
beer.push(data.beer[i].beer_name);
country.push(data.beer[i].brewery_country);
}
}
showBeerList();
}
function showBeerList() {
var select = document.getElementById('beerListing');
for (var i = 0; i < beer.length; i++) {
var obj = document.createElement("option");
obj.text = beer[i];
obj.value = i;
select.appendChild(obj);
}
}
function getBeerInfo(picked) {
if (picked == "Pick Your Poison...") {
location.reload();
}
else {
document.getElementById("name").innerHTML = beer[picked];
document.getElementById("country").innerHTML = country[picked];
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>LCBO API TESTING</h1>
<select name="beerlist" id="beerListing" class="form-control" onchange="getBeerInfo(this.value)">
</select>
<br>
<label>Name:</label>
<label id="name">--</label>
<br>
<label>Country:</label>
<label id="country">--</label>
<br>
I got it working here: https://jsfiddle.net/bu7pkb5f/1/
What are you doing with:
if (beer.indexOf(data[x].beer_name) < 0) {
var y = beer.length;
beer[y] = data[x].beer_name;
country[y] = data[x].brewery_country;
}
I don't understand it but it's creating a third item in the list after the two real beer entries are processed. I left it commented out in the fiddle so you can check it out for yourself.

How to create multiselect to show detail of each selected in Django?

Description Image Demo
I want to create a small demo like the picture if I click the item in the left column to choose the Country and the right column will display all the city of country in the left column that I chosen. How can I do that?
I wrote a small sample, I hope it helps you:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<style>
select {
min-width: 100px;
float: left;
margin-right: 20px;
}
</style>
</head>
<body>
<select id="countrySelect" size="10"></select>
<select id="citySelect" size="10"></select>
<script>
var countries = [{name: "USA", id:1}, {name: "Canada", id:2}];
var cities = [{name: "New York", id:1, countryId:1}, {name: "Boston", id:2, countryId:1}, {name: "Ottawa", id:3, countryId:2}, {name: "Toronto", id:4, countryId:2}];
var $countrySelect = $('#countrySelect');
var $citySelect = $('#citySelect'), countrySelectHtml = '';
for (var i=0; i<countries.length; i++) $countrySelect.append($('<option>').attr('value', countries[i].id).text(countries[i].name));
$countrySelect.change(function () {
var countryId = $countrySelect.val();
$citySelect.html('');
for (var i=0; i<cities.length; i++)
if (cities[i].countryId == countryId) $citySelect.append($('<option />').attr('value', cities[i].id).text(cities[i].name));
});
$citySelect.change(function () {
alert('Selected city: ' + $(this).find('option:selected').text() + ' (id=' + $citySelect.val() + ')');
});
</script>
</html>

Object with array in localstorage

I am trying to make an object with array, every object should have array of file names. I named the object as productid, which can have multiple file names. When the customer gives the productid, the file names must be displayed in the text area. I have the following code:
<!DOCTYPE html>
<html>
<title>W3.CSS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">
<script type="text/javascript">
var productid = []
var filename = []
function managerClick(){
console.log("manager", productid);
console.log("manager", filename);
productid.push(document.getElementById("productId").value);
filename.push(document.getElementById("names").value);
localStorage.setItem("filename", JSON.stringify(filename));
localStorage.setItem("productid", JSON.stringify(productid));
var result={}
productid.map(function(k){
result[k]=filename;
})
console.log(result);
document.getElementById('myTextarea').value = "";
document.getElementById('CustomerpId').value = "";
};
function customerClick(){
document.getElementById('myTextarea').value = "";
var CustomerpId = document.getElementById('CustomerpId').value;
var filenames = JSON.parse(localStorage.getItem("filename"));
var productIds= JSON.parse(localStorage.getItem("productid"));
var tempArr = [];
for(i=0; i< productIds.length; i++) {
if(productIds[i] == CustomerpId) {
tempArr.push(i);
}
}
for(i=0; i< tempArr.length; i++) {
document.getElementById('myTextarea').value += filenames[tempArr[i]] + ",";
}
};
</script>
<body>
<div class="w3-card-4 w3-margin" style="width:50%;">
<center>Manager</center>
<div class="w3-container">
Product Id: <input type="text" id="productId"><br></br>
File Name: <input type="text" id="names"><br></br>
<center><button class="w3-btn w3-dark-grey" onclick="managerClick()">Data Entered</button></center><br>
</div>
<center>Customer</center>
<div class="w3-container">
Product Id: <input type="text" id="CustomerpId"><br></br>
<center>
<button class="w3-btn w3-dark-grey" onclick="customerClick()">Click To get filename</button>
</center><br>
<textarea rows="4" cols="30" id="myTextarea"></textarea>
</div>
</div>
</body>
</html>
The issue with this code is that whenever I enter my productid in my customer section, the array of all file names is being displayed. I want to display only the array of a specific productid:
example: product1[ file1,file2,file3]
product2[ file1,file2,file3,file4]
product3[ file1]
the array in that product should be displayed, if a specific product is given then data in that product has to be displayed, the above code displays it like this:
inputs i gave 1 as productid "a,aa,aaa", 2as second productid and "b,bb,bbb" as file name. In my console a,aa,aaa and b,bb,bbb are been displayed in both the products i dont want this to happen. All a,aa,aaa should be in 1st product and all b,bb,bbb should be saved in 2nd product. Every product should display its own values.
Try this function:
function customerClick(){
document.getElementById('myTextarea').value = "";
var CustomerpId = document.getElementById('CustomerpId').value;
var filenames = JSON.parse(localStorage.getItem("filename"));
var productIds= JSON.parse(localStorage.getItem("productid"));
var tempArr = [];
for(i=0; i< productIds.length; i++) {
if(productIds[i] == CustomerpId) {
tempArr.push(i);
}
}
for(i=0; i< tempArr.length; i++) {
document.getElementById('myTextarea').value += filenames[tempArr[i]] + ",";
}
};
On Click of Get Field Name, You have to get id for which you want to show and then perform operations on productid array and filenames array.
EDIT : As per you mentioned in comments here is updated code:
function managerClick() {
var productid = document.getElementById("productId").value;
var filename = document.getElementById("names").value;
var oldItems = JSON.parse(localStorage.getItem(productid)) || [];
var newItem = filename;
oldItems.push(newItem);
localStorage.setItem(productid, JSON.stringify(oldItems));
}
function customerClick() {
document.getElementById('myTextarea').value = "";
var CustomerpId = document.getElementById('CustomerpId').value;
var productIds = JSON.parse(localStorage.getItem(CustomerpId));
for(i=0;i<productIds.length;i++) {
document.getElementById('myTextarea').value += productIds[i] + ",";
}
}
Hope this helps.

How to prevent selected index from changing when bound data changes?

Using knockout, I have a select (a list of names) whose options are bound to another set of knockout-bound data (people). When the name of any person changes, the value of the select option that is bound to that person's name is correctly updated. However, the select's selection is not preserved if you had that person selected already.
See this jsFiddle for a live example: http://jsfiddle.net/DbBZQ/
Select "Jane" from the list.
Change the name "Jane" to something else ("Jane Doe" for example).
Notice the select defaults back to the first item.
How can I make the selection stick to the same option index even if the underlying value has changed? Is there a way to instruct knockout to preserve the selection or do I have to do this separately using JS?
Complete Code Example
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript" src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
var data =
{
people: ko.observableArray(
[
{ name: ko.observable("Jim") },
{ name: ko.observable("Jane") },
{
name: ko.observable("Sam"),
subordinates: ko.observableArray(
[
{
name: ko.observable("Tambone"),
subordinates: ko.observableArray(
[
{ name: ko.observable("Edward") },
{ name: ko.observable("Kristy") },
{ name: ko.observable("Thomas") },
{ name: ko.observable("Andy") }
])
},
{ name: ko.observable("Jules") }
])
}
])
};
var allNames = ko.computed(function ()
{
var names = [];
var selector = function (name, indent)
{
var option =
{
value: name,
text: (indent || "") + name
};
return option;
};
for (var i = 0; i < data.people().length; i++)
{
names.push(selector(data.people()[i].name()));
addSubordinates(names, 1, data.people()[i].subordinates, selector);
}
return names;
});
function addSubordinates(names, depth, subordinates, selector)
{
if (subordinates != null)
{
var indentText = "";
for (var i = 0; i < depth; i++)
indentText += ". . ";
for (var i = 0; i < subordinates().length; i++)
{
names.push(selector(subordinates()[i].name(), indentText));
addSubordinates(names, depth + 1, subordinates()[i].subordinates, selector);
}
}
}
</script>
</head>
<body>
<div data-bind="foreach: data.people">
<input type="text" data-bind="value: name" /><br />
</div>
Add Person
<br /><br /><br />
<select data-bind="options: allNames, optionsValue: 'value', optionsText: 'text', optionsCaption: 'All Names...'" />
<script type="text/javascript">
ko.applyBindings();
</script>
</body>
</html>
The reason the selection is lost is because the selected value is matched directly to the name property, which changes. As a result, the selected value no longer exists in the data source (allNames).
If you want to retain the selection, you have a couple of options:
Implement a hack such as tracking the index, and resetting it after the value changes
Bind the selected value to a property that doesn't change.
Do you have an immutable property that you can use as the selected value?
For the sake of an example, I added an id property to the objects in the data source, and use that as the selected value instead of name. This works the way you expect:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript" src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
var data =
{
people: ko.observableArray(
[
{ id: 1, name: ko.observable("Jim") },
{ id: 2, name: ko.observable("Jane") },
{
id: 3, name: ko.observable("Sam"),
subordinates: ko.observableArray(
[
{
id: 4, name: ko.observable("Tambone"),
subordinates: ko.observableArray(
[
{ id: 5, name: ko.observable("Edward") },
{ id: 6, name: ko.observable("Kristy") },
{ id: 7, name: ko.observable("Thomas") },
{ id: 8, name: ko.observable("Andy") }
])
},
{ id: 9, name: ko.observable("Jules") }
])
}
])
};
var allNames = ko.computed(function ()
{
var names = [];
var selector = function (id, name, indent)
{
var option =
{
value: id,
text: (indent || "") + name
};
return option;
};
for (var i = 0; i < data.people().length; i++)
{
names.push(selector(data.people()[i].id, data.people()[i].name()));
addSubordinates(names, 1, data.people()[i].subordinates, selector);
}
return names;
});
function addSubordinates(names, depth, subordinates, selector)
{
if (subordinates != null)
{
var indentText = "";
for (var i = 0; i < depth; i++)
indentText += ". . ";
for (var i = 0; i < subordinates().length; i++)
{
names.push(selector(subordinates()[i].id,subordinates()[i].name(), indentText));
addSubordinates(names, depth + 1, subordinates()[i].subordinates, selector);
}
}
}
</script>
</head>
<body>
<div data-bind="foreach: data.people">
<input type="text" data-bind="value: name" /><br />
</div>
Add Person
<br /><br /><br />
<select data-bind="options: allNames, optionsValue: 'value', optionsText: 'text', optionsCaption: 'All Names...'" />
<script type="text/javascript">
ko.applyBindings();
</script>
</body>
</html>
Edit:
As an alternative, what if you set up the value property so that it was a ko.computed that returned the index of the item? Like this:
var allNames = ko.computed(function ()
{
var names = [];
var selector = function (item, name, indent)
{
var option =
{
value: ko.computed(function(){ return data.people().indexOf(item);}),
text: (indent || "") + name
};
return option;
};
for (var i = 0; i < data.people().length; i++)
{
names.push(selector(data.people()[i], data.people()[i].name()));
addSubordinates(names, 1, data.people()[i].subordinates, selector);
}
return names;
});
function addSubordinates(names, depth, subordinates, selector)
{
if (subordinates != null)
{
var indentText = "";
for (var i = 0; i < depth; i++)
indentText += ". . ";
for (var i = 0; i < subordinates().length; i++)
{
names.push(selector(subordinates()[i],subordinates()[i].name(), indentText));
addSubordinates(names, depth + 1, subordinates()[i].subordinates, selector);
}
}
}

Categories