0
votes

I am trying to use knockout with MVC strongly typed view. Since my model will have over 20 properties, I prefer to use strongly-typed view model to post back data by using ko.mapping.toJS and ko.Util.postJson. The Eligible field was passed back correctly, however the following code does not post back the selected option from drop down list, it just showed value as 0 when I looked that selectOptionModel on the controller. Can someone point out what I did wrong?

the view model from server side is as follows:

  public class SelectOptionModel
{
    public bool Eligible { get; set; }
    public int selectedOption { get; set; }
    public IEnumerable<SelectListItem> AvailableOptions
    {
        get
        {
            return Enum.GetValues(typeof(OptionEnum)).Cast<OptionEnum>()
            .Select(x => new SelectListItem
            {
                Text = x.ToString(),
                Value = x.ToString()
            });
        }
    }
}
public enum OptionEnum
{
    [Description("First")]
    FirstOption = 1,
    [Description("Second")]
    SecondOption = 2,
    [Description("Third")]
    ThirdOption = 3
}

The razor view is like following:

@model TestKo.Models.SelectOptionModel
...
subViewModel = ko.mapping.fromJS(@Html.Raw(Json.Encode(Model)));
...
}
@using (Html.BeginForm()){
 <button type="submit" class="button" id="SaveBtn">Save</button>           
 <div data-bind="with:vm">
<div>
        @Html.LabelFor(model => model.Eligible)
        @Html.CheckBoxFor(model => model.Eligible, new { data_bind = "checked: selectOptionVM.Eligible" })
    </div>
    <div>
            @Html.LabelFor(model => model.selectedOption)
            @Html.DropDownListFor(model => model.selectedOption, Model.AvailableOptions,
         new
        { data_bind = "options: selectOptionVM.AvailableOptions, optionsText: 'Text', optionsValue: 'Value', value: selectOptionVM.selectedOption"
      })
        </div>
</div>
}

The javascript for the knockout view model is:

sectionVM = function (data) {

    var self = this;
    var selectOptionVM = data;
    return {
    selectOptionVM: selectOptionVM
    }
}

$(document).ready(function () {

var viewModel = {
    vm: new sectionVM(subViewModel)
};

ko.applyBindings(viewModel);

$("#SaveBtn").click(function () {
    var optionModel = ko.toJS(viewModel.vm.selectOptionVM);
    ko.utils.postJson($("form")[0], optionModel)

});
}); 

The controller part:

[HttpPost]
    public ActionResult Create(SelectOptionModel selectOptionModel)
    {
        try
        {
            // TODO: Add insert logic here
            var modelSaved = selectOptionModel;
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }

2
I also tried c-sharpcorner.com/uploadfile/5ff76e/… to add FromJsonAttribute, but during model binding, the stringfied value was null, therefore the model passed to the controller was null. I don't know what went wrong. - AlliceSmash
i am fairly new to knockout myself, but the one thing I don't see is anywhere you are setting your knockout properties to observables. - mmeasor
@mmeasor, That's being done in ko.mapping.fromJS(). - haim770
@AlliceSmash, Do you see any console errors? - haim770
@haim770: no console errors :( I also checked optionModel before .postJson, the selectedOption is correct. So the value got lost from postJson to controller. I am not quite sure how to debug it - AlliceSmash

2 Answers

0
votes

I'm venturing a bit of a guess here, but this could be the problem: the id-bit of your selected option will always be a string (because it will go in the <option value="" attribute). Your endpoint expects an int. As far as I can see, you don't convert the selectedOption before sending it to the server. try parseInt(selectedOption, 10) before sending it to the server. Also, use the network tool in your browser to debug the info that is being sent to the controller. That might help you to zone in on the problem.

0
votes

Actually it works. Somehow it was not working previously, but after I cleared cache, cookies etc, it just worked. Thanks everyone!