简体   繁体   中英

Populating MVC3 view model with a selected value from a JavaScript/Knockout dropdown?

I'm looking for advice on how to populate the viewmodel passed to the view after a list is retrieved and an item selected in a dropdown list. Note that I also have a client side viewmodel that is used for the Ajax/Knockout client code but this is not the view model that I am trying to populate. I may have to map from one view model to the other but I'm not sure if that is the correct solution.

View - Form

In my form I am using Knockout and JavaScript for my dropdowns. How can I populate the view model m.VMResidencyWTCS.ScCountyCd field with the county code value that is selected? Is it possible to also capture the desription? If so, how would this be done as well?

@model Apps.Model.ViewModels.AVMApplicationInfo
...
@using (Html.BeginForm("ApplicationDetails", "PersonalInfo"))
{
    <fieldset>
        <div class="appl-step">
      ...
            <div class="editor-label">
                <span class="error">*</span>@Html.LabelFor(m => m.VMResidencyWTCS.ScCountyCd) 
            </div>
            <div class="editor-field">
                <select id='counties' 
                        data-bind='
                            options: selectedResidencyState() ? counties : null, 
                            optionsValue : "CountyCd", 
                            optionsText: "CountyDescr", 
                            optionsCaption: "[Please select a county]", 
                            value: selectedCounty,
                            visible: (counties() && counties().length > 0 )'>
                </select>
                <span data-bind='
                    template: {name: "noInfoTemplate"},
                    visible: !(counties() && counties().length > 0)'>
                </span>
            </div>

View - JavaScript

This is my script for calling back to the controller for the county dropdown list. Note that the county dropdown is populated when a state is selected in another dropdown.

<script type='text/javascript'>
    $(document).ready(function () {
    var residency = function () {
        this.selectedResidencyState = ko.observable();
        this.selectedCounty = ko.observable();
                    ...
        this.states = ko.observableArray();
        this.counties = ko.observableArray();
     ...

        this.selectedResidencyState.subscribe(function (stateCd) {
            this.selectedCounty(undefined);
            this.counties(undefined);

            if (stateCd != null) {
                $.ajax({
                    url: '@Url.Action( "GetCounties", "PersonalInfo")',
                    data: { stateCd: stateCd },
                    type: 'GET',
                    success: function (data) {
                        residencyViewModel.counties(data);
                    }
                });
            }
        } .bind(this));

    };

    var residencyViewModel = new residency();
    ko.applyBindings(residencyViewModel);

    //Load the states
    $.ajax({
        url: '@Url.Action( "GetResidencyStates", "PersonalInfo" )',
        type: 'GET',
        success: function (data) {
            residencyViewModel.states(data);
        }
    });
});
</script>

Controller

public class PersonalInfoController : Controller
{
…
    [HttpGet]
    public virtual ActionResult GetCounties(string stateCd)
    {
        var counties =
            (
                from county in this._countyRepository.All
                where (county.CountryCd == "USA" && county.ResidencyStateCd == stateCd)
                select new
                {
                    CountyCd = county.CountyCd,
                    CountyDescr = county.CountyDescr,
                    StateCd = county.ResidencyStateCd,
                    CountryCd = county.CountryCd // Added for populating model ?Needed?
                }
            ).ToList();

        return Json(counties, JsonRequestBehavior.AllowGet);
    }

Note that I also have a client side viewmodel that is used for the Ajax/Knockout client code but this is not the view model that I am trying to populate. I may have to map from one view model to the other but I'm not sure if that is the correct solution.

Ok, there are some yellow flags going up.

Let me restate your question to verify my understanding: you've got a view model with an observable bound to a <select> box. Let's pretend it's vm1.mySelection.

You have a 2nd view model, and you want to store vm1.mySelection inside vm2.mySelection.

Is that correct?

If so, my first thought is, "You're probably doing it wrong." Please explain why you think you need this, and we'll tell you whether there's a better way.

Secondly, if you truly do need this, you could manually subscribe to vm1.mySelection inside vm2, then set the value accordingly in vm2. But again, this feels hackish, and you might be doing it wrong.

My design may be not be the best. I have a view model being passed to the view from the server as defined in the view statement ( @model Apps.Model.ViewModels.AVMApplicationInfo ). I use this extensively in the view "form" to capture information to build a web service call.

I needed to add some cascading dropdowns to get filtered information. To do this I added the knockout code and the clientside view model (var residencyViewModel = new residency(); ko.applyBindings(residencyViewModel); ). This is used to call back to the controller via ajax to get the dropdown values. Once the dropdown value has been selected I would like to store the selection in the Apps.Model.ViewModels.AVMApplicationInfo view model. I'm not sure if I need the clientside view model but I'm not sure how else to code this.

The selected value would also be used for subsequent cascading dropdowns (as another filter value). Some dropdowns use the selected values from multiple dropdowns selected earlier in the form; ie, they have more than one filter such as: country, state, county, municipality. This is due to the table structure which can't be changed. Ultimately though when all the selections have been made the Apps.Model.ViewModels.AVMApplicationInfo view model must be populated with all the selections to pass the values back to the server for the web service call.

Does that make sense?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM