Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout.js & list of checkboxes: post to mvc controller

I have an MVC view model that looks like this:

public class DirectorySearchModel
{
    [Display(Name = "First name contains")]
    public string FirstName { get; set; }

    [Display(Name = "Last name contains")]
    public string LastName { get; set; }

    public CountriesCollection Countries { get; set; }
    public IEnumerable<Country> SelectedCountries { get; set; }
    public IEnumerable<Country> AllCountries { get; set; }
}

The CountriesCollection object (line 9) looks like this:

public class CountriesCollection
{
    [Display(Name = "Countries")]
    public int[] arrCountries { get; set; }
}

Now, I'm creating a new, blank instance of CountriesCollection and then adding it to a blank instance of the DirectorySearchModel view model and then serialising it all into a javascript view model for Knockout.js:

{
"FirstName":null,

"LastName":null,

"Countries":{"arrCountries":[]},

"SelectedCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}],

"AllCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}]
}

My checkboxes are rendered as: <input checked="checked" data-bind="checked: Countries.arrCountries" id="Countries_arrCountries30" name="Countries.arrCountries" type="checkbox" value="1">. Checking a couple means you end up with this Knockout.js view model:

{
"FirstName":null,

"LastName":null,

"Countries":{"arrCountries":["1", "3"]},

"SelectedCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}],

"AllCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}]
}

Submitting my view normally (i.e. via a submit button and not with Knockout.js) to an MVC action that expects a DirectorySearchModel, I'm able to ask for model.Countries.arrCountries to get a list of the checked items, but when I use...

$.post("/MyController/MyAction", ko.toJS(viewModel), function(returnData) {
    $("#resultCount").html(returnData);
});

or...

$.post("/MyController/MyAction", viewModel, function(returnData) {
    $("#resultCount").html(returnData);
});

to another action that expects the same DirectorySearchModel, model.Countries.arrCountries is always null! I wondered if it's due to Knockout.js posting the arrCountries entries as string[]s when MVC is expecting int[]s, but changing my MVC code to expect string[]s doesn't seem to change much..! The CountriesCollection object within the DirectorySearchModel appears to exist, but it's the arrCountries within that's always null.

Any ideas? Any help much appreciated!

Edit

The action that receives the Knockout.js viewModel:

public MvcHtmlString ResultCount(DirectorySearchModel model)
{
    return new MvcHtmlString(getResultCount(model).ToString());
}

The getResultCount method:

public int getResultCount(DirectorySearchModel model)
{
    IUserRepository userRepository = new UserRepository();
    int count = userRepository.Search(model, null).Count();
    return count;
}

FIXED!

Thanks to Konstantin for pointing out that a simple switch from $.post to $.ajax to send my Knockout.js view model back to my mvc action was all that was needed! Here's the $.ajax code I'm using:

$.ajax({  
    type: "POST",
    url: "/MyController/MyAction",
    data: ko.toJSON(viewModel),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (data) {
        $("#resultCount").html(data);
    }
});
like image 301
user1390429 Avatar asked May 22 '12 08:05

user1390429


People also ask

What is KnockoutJS used for?

Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model.

Is Knockout still used?

KnockoutJS is far from dead, and it's actually still being improved and evolved (see Technical Knockout) but newer frameworks seem a far better bet for our needs, considering activity and performance.

What is the difference between KnockoutJS and Angular js?

Think of it this way: Knockout is primarily used to control UI representation in lower complexity applications, whereas Angular is a JavaScript framework that is much better suited for large, complex enterprise applications.

What is model KnockoutJS?

KnockoutJS is basically a library written in JavaScript, based on MVVM pattern that helps developers build rich and responsive websites. The model separates the application's Model (stored data), View (UI) and View Model (JavaScript Representation of model).


1 Answers

You cant use $.post you need to go for the underlying $.ajax and add the correct contenttype to make mvc accept the posted json and do the model binding (contenttype should be "application/json; charset=utf-8") google for it and you will se lots of examples

like image 124
Konstantin Avatar answered Nov 08 '22 02:11

Konstantin