0
votes

I am trying to use knockout to bind dropdowns to an observableArray for the options list. As far as I can tell, I have followed the examples I've found, but it is not working. Below are the relevant parts of my code. This is in a cshtml file in an MVC app, so you'll see some Razor syntax in there.

$(function () {
  var $thisdd = $("#@ddname");  //the JQuery selector for my dropdown
  var dropdownItems = new ko.observableArray();

  dropdownItems = getDropdownItemsFromDl("@ddname");

  var newitem = ko.observable({ cname: ddcname, cvalue: ko.observable($thisdd.val()), cpublishtopic: "" });
  classificationsViewModel.push(newitem());
  $thisdd.attr("data-bind", "options: dropdownItems, optionsText: function(item) { return item.value; }, optionsValue: function(item) { return item.key; }, value: classificationsViewModel()[" + classificationsViewModel.indexOf(newitem()) + "].cvalue ");
  ko.applyBindings(newitem);
});

After the call to getDropdownItemsFromDl, dropdownItems looks like this in the Chrome debug watch window:

dropdownItems(): Array[14]
0: Object
key: "0"
value: "none"
__proto__: Object
1: Object
key: "1"
value: "Equity Portfolio"
__proto__: Object
2: Object
key: "2"
value: "Fixed Income Portfolio"
__proto__: Object
3: Object
4: Object
5: Object
6: Object
7: Object
8: Object
9: Object
10: Object
11: Object
12: Object
13: Object
length: 14
__proto__: Array[0]

classificationsViewModel is a ko.observableArray. cvalue is a ko.observeable property of objects in that array.

The dropdown options list ends up with only "None", the first item in the array. What is wrong with my binding attribute?

1
Before diving into this, did you call ko.applyBindings(viewmodel, element ) anywhere? I don't see it. This call will bind your viewmodel to your DOM; - muck41
Thanks for pointing out the omission, muck41. Yes, that line was already in my code and I've updated the posting. - EVal
I think you can't use a function for the optionsValue binding. It needs to be a string with the name of the property (e.g. 'key'). In most cases using optionsValue is not the way to go, as you want the values to be maintained by KO - antishok

1 Answers

0
votes

I got this to work AS LONG AS the binding to the value is the last script line. Any javascript after that ko.applyBinding line will not be executed! I will be creating another question to address that wierdness as this is a serious problem for my app.

Notice that I ended up using a viewModel. I could not get binding directly to the observableArray to work.

Also note that value: preceeds the options: in the data-bind attribute. When I had value: as the last part of the attribute, the options bind did not work.

Here are the relevant lines of my code that "work".

$(function () {   
  var $thisdd = $("#@ddname");  //the JQuery selector for my dropdown   

  var dropdownItems = getDropdownItemsFromDl("@ddname");    
  var newitem = ko.observable({ cname: ddcname, cvalue: ko.observable($thisdd.val()), cpublishtopic: "" });   
  classificationsViewModel.push(newitem());   

  var viewModel =
    {
        dditems : dropdownItems 
    };

  $("#@ddname").attr("data-bind", "value: classificationsViewModel()[" + classificationsViewModel.indexOf(newitem()) + "].cvalue, options: dditems, optionsText: 'value', optionsValue: 'key'");
  ko.applyBindings(viewModel);
  ko.applyBindings(classificationsViewModel()[classificationsViewModel.indexOf((newitem())].cvalue);
});

I hope that this "answer" helps someone else struggling with this issue.