Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Persisting knockout ViewModel between ASP.NET WebForms server side posts ...

Using this article posted on CodeProject.com, "Using KnockoutJS in your ASP.NET applications" as a guide I am attempting to create a reusable, data-loaded drop down list using ASP.NET 3.5 Web Forms, but that leverages KnockoutJS for client-side data-binding. Multiple, independent instances of this drop down should be able to live independently in the same page.

So far the CodeProject.com post has been invaluable in directing me on how to set things up and I am successfully passing the updated ViewModel data back and forth between the server and client as a JSON string and converting it to and from an object (both on the server and client). What I am hanging up on is what should be the simple part; binding the ViewModel to the drop down list!

So I begin by loading the JSON string into a hidden field. It includes a list of Regions and a single SelectedRegion.

<input type="hidden" id="ddlRegionKO_hdnRegionListVMStorage" value="{&quot;Regions&quot;:[{&quot;RegionName&quot;:&quot;Mid Atlantic USA&quot;,&quot;RegionId&quot;:2},{&quot;RegionName&quot;:&quot;Mid West USA&quot;,&quot;RegionId&quot;:10},{&quot;RegionName&quot;:&quot;North Central USA&quot;,&quot;RegionId&quot;:5},{&quot;RegionName&quot;:&quot;North East USA&quot;,&quot;RegionId&quot;:1},{&quot;RegionName&quot;:&quot;North West USA&quot;,&quot;RegionId&quot;:7},{&quot;RegionName&quot;:&quot;Other&quot;,&quot;RegionId&quot;:9},{&quot;RegionName&quot;:&quot;South Central USA&quot;,&quot;RegionId&quot;:6},{&quot;RegionName&quot;:&quot;South East USA&quot;,&quot;RegionId&quot;:3},{&quot;RegionName&quot;:&quot;South West USA&quot;,&quot;RegionId&quot;:8}],&quot;SelectedRegion&quot;:{&quot;RegionName&quot;:&quot;North Central USA&quot;,&quot;RegionId&quot;:5}}" />

I then run convert this string into a Javascript Object using the ko.utils.parseJson() function.

var stringViewModel = document.getElementById("ddlRegionKO_hdnRegionListVMStorage").value;
var ddlRegionKO_pnlRegionDDLContainer_ViewModel = ko.utils.parseJson(stringViewModel);

Then I convert the property definitions into ko.observable and ko.observableArray methods (this is one of those sections that will be need to be refactored, but as a proof of concept it suffices).

//
// Convert all the model properties to KO Propety/Methods
for (var propertyName in ddlRegionKO_pnlRegionDDLContainer_ViewModel) {
    switch(propertyName.toUpperCase())
    {
        //
        // Multiple Region objects are stored as an array in the regions property.
        case "REGIONS":
            ddlRegionKO_pnlRegionDDLContainer_ViewModel[propertyName] = ko.observableArray(ddlRegionKO_pnlRegionDDLContainer_ViewModel[propertyName]);
            break;
        //
        // Only a single region may be selected at any time.
        case "SELECTEDREGION":
            ddlRegionKO_pnlRegionDDLContainer_ViewModel[propertyName] = ko.observable(ddlRegionKO_pnlRegionDDLContainer_ViewModel[propertyName]);
        break;
    };
};

Given this, I would expect the drop down list to be populated and the SelectedRegion selected when the applyBindings method is called ...

ko.applyBindings(ddlRegionKO_pnlRegionDDLContainer_ViewModel);

I have put this all together at JSFiddle ... here ... I suspect that I may be overlooking something but I cannot see what it might be. Everything looks right to me.

If anybody can see something that I am overlooking I would be extremely grateful!

Thanks,

-g

like image 520
Gary O. Stenstrom Avatar asked Nov 03 '22 07:11

Gary O. Stenstrom


1 Answers

You don't need to specify the model name in your bindings. Instead of options:ddlRegionKO_pnlRegionDDLContainer_ViewModel.Regions, just use options:Regions, etc.

<select id="ddlRegionKO_ddlRegionList" 
    data-bind="options:Regions, 
        optionsText:'RegionName', 
        optionsValue:'RegionId',
        value:SelectedRegion, 
        optionsCaption:'Choose Region ...'">
</select>

Working fiddle

Edit: You were also missing an optionsValue binding that specified which property you want to be bound to the value of each option. I updated the fiddle to include this change.

Edit 2: Well, your selected region in your json is an object. I looked over the knockout documentation about binding and I didn't see a way to bind a selected value to an object, so if it's possible for you to modify the json, you can just specify the id of the selected value.

<input type="hidden" 
    id=".."
    data-bind="..a bunch of array stuff...  ,&quot;SelectedRegion&quot;:5}" 
/>

See what I did there? I replaced the object

'SelectedRegion':{'RegionName':'North Central USA','RegionId':5}

with just:

'SelectedRegion':5

Updated fiddle is here. But this won't help with your textbox situation because it will show the ID instead of the text in your textbox. It's a bit late here so I'm not really sure how to fix that off hand, but you might look here for some inspiration. Good luck.

like image 169
hawkke Avatar answered Nov 08 '22 05:11

hawkke