Frage

I would like to make my SelectList observable so the ViewModel gets updated with changes made to that SelectList. I see the values displayed in the drop down list in my UI but I never see that selected value updated in my ViewModel, It is always null. I have other controls on the form that are updated without issue so I would like to know how, specifically, to make a SelectList observable. It seems SelectLists and knockout are a little different than a standard input control.

I have the following in a class:

public string LocationId { get; set; }
public IEnumerable<SelectListItem> Locations { get; set; } 

I have the following that populates my array of locations:

 private PersonViewModel _viewModel;

 public ActionResult Index()
 {
    var locations = new[]
    {
        new SelectListItem { Value = "US", Text = "United States" },
        new SelectListItem { Value = "CA", Text = "Canada" },
        new SelectListItem { Value = "MX", Text = "Mexico" },
    };

    _viewModel.Locations = locations;
     return View(_viewModel);
}

I have the following in my markup:

<script type="text/javascript">
    Person.ViewModel = ko.mapping.fromJS(@Html.Raw(Json.Encode(Model)));
    var locationsArray = ko.observableArray(@Html.Raw(Json.Encode(Model.Locations)));
</script>

<form>
  <table>
    <tr>
        <td>
            Locations: 
        </td>
        <td>
           @Html.DropDownListFor(model => model.LocationId, new SelectList(Model.Locations, "Value", "Text"), new { id = "locationsArray" })
        </td>
    </tr>
  </table>
</form>
War es hilfreich?

Lösung

Create One Get method as you write in Index method that returns Value and Text field structure. Like

 public ActionResult GetALL()
     {

        var data = new[]
        {
            new SelectListItem { Value = "US", Text = "United States" },
            new SelectListItem { Value = "CA", Text = "Canada" },
            new SelectListItem { Value = "MX", Text = "Mexico" },
        };

         return Json(data, JsonRequestBehavior.AllowGet); 

    }

and your ViewModel like this

var DataTable = function(obj) {
    var self = this;
    self.Text  = obj.Text;
    self.Value  = obj.Value;
    self.Selected = obj.self;
};
var viewModel = function() {
        var self = this;
        self.list = ko.observableArray([]);
         $.ajax({
            url: "@Url.Action("GetALL", "Home")",
            dataType: 'json',
            async: false,
            success: function (data) {
                self.list.removeAll();
                $.each(data,function(index,d) {
                    self.list.push(new DataTable(d));
                });

            },
            error: function (xhr, e, s) {
            }
        });

    };

Your select

<select data-bind="options: list, optionsText: 'Text', optionsValue: 'Value', optionsCaption: 'Select'"></select>

Andere Tipps

You could do this...

<p>Locations:
    <select data-bind="options: countries, optionsText: 'shortcountry', optionsValue: 'country', optionsCaption: 'Select'"></select>
</p>

And ViewModel...

var countriesVM = {
            countries: [{
                shortcountry: 'US',
                country: 'United States',
                disable: ko.observable(false)
            }, {
                shortcountry: 'CA',
                country: 'Canada',
                disable: ko.observable(true)
            }, {
                shortcountry: 'MX',
                country: 'Mexico',
                disable: ko.observable(false)
            }]
        };

        ko.applyBindings(countriesVM);

See the fiddle here.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top