My View is bound to a Model and displays several dropdown lists, and their number and the options are based on some properties in the model.
I would like to use knockout js to data bind each selected value of the dropdown lists to an observable array, keeping track of which value belongs to which ddl.
Each dropdown list is displayed using the following code:
@for (var i = 0; i < Model.ProductProfiles.Count; i++)
{
var productProfile = Model.ProductProfiles[i];
if (productProfile.IsVarying)
{
var lastItem = 0;
<div class="tab-pane" id="@productProfile.Name">
@for (var j = 0; j < productProfile.Attributes.Count; j++)
{
<text>@productProfile.Attributes[j].Name</text>
@Html.DropDownListFor(m => m.ProductProfiles[i].SelectedValues[j], (SelectList)ViewData["Levels_" + i + "_" + j],
new { @class = "ddl-levels" })
<br />
}
</div>
}
}
The dropdownlists are correctly filled in and the default value is correctly set (using both the model and the select list passed in the ViewData).
Is there a way to databind to an array that looks something like:
array[0][“0”, “1”, “3”, “1”,….] where array[0] refers to Model.ProductProfiles[0] and the second dimension of the array holds the selected values for the ddl as displayed in the for loop
?
I tried setting my view model as simple as
var viewModel = {
selectedValues: ko.observableArray([])
};
and out of desperation I tried to modify the data-bind value to simulate a positional access in the observable array:
@Html.DropDownListFor(m => m.ProductProfiles[i].SelectedValues[j], (SelectList)ViewData["Levels_" + i + "_" + j],
new { @class = "ddl-levels", data_bind = "value: productProfiles([" + i + "][" + j + "])" })
Unfortunately it didn’t work…
I hope to have been clear, otherwise I would be glad to clarify when asked to.
Is there anyone who can help me?
Thanks
EDIT: based on comment advice, I split the multidimensional array into 3 observable arrays
like the following:
var viewModel = {
selectedValuesProd0: ko.observableArray(),
selectedValuesProd1: ko.observableArray(),
selectedValuesProd2: ko.observableArray()
}
and then I modified the HTML code
var observableArrayProduct = "selectedValuesProd0";
if (i == 1)
{
observableArrayProduct = "selectedValuesProd1";
}
else if (i == 2)
{
observableArrayProduct = "selectedValuesProd2";
}
@Html.DropDownListFor(m => m.ProductProfiles[i].SelectedValues[j], (SelectList)ViewData["Levels_" + i + "_" + j], new { @class = "ddl-levels", data_bind = "value: " + observableArrayProduct + "()[" + j+ "]" })
As you can see I’m still trying a positional access to the mono-dimensional observable array, but it’s still not keeping track of the selected values when the user changes something in the DropDown lists.
At this point I’m starting to think that positional access doesn’t work, but if that’s so, what else can I do?
EDIT 2: SOLVED!
Ok, I was missing a key step: each item in the observable array is itself an observable value, so I fixed it like the following:
var viewModel = {
selectedValuesProd0: ko.observableArray(ko.utils.arrayMap(selectedValuesPerProduct[0], function(item) {
return ko.observable(item);
})),
selectedValuesProd1: ko.observableArray(ko.utils.arrayMap(selectedValuesPerProduct[1], function(item) {
return ko.observable(item);
})),
selectedValuesProd2: ko.observableArray(ko.utils.arrayMap(selectedValuesPerProduct[2], function(item) {
return ko.observable(item);
}))
}
Where selectedValuesPerProduct is a bidimensional array built using the model passed from the server side code to the View (after serialization).
I hope this can help!
I realised I had never closed this question, so I’m adding a response here:
Ok, I was missing a key step: each item in the observable array is itself an observable value, so I fixed it like the following:
}
Where selectedValuesPerProduct is a bidimensional array built using the model passed from the server side code to the View (after serialization).