AlanMorton2.0
AlanMorton2.0

Reputation: 1053

.NET MVC 4 list with KnockoutJS data-bind'ing

Ok so i have a view with this so far

 function AppViewModel() {
                this.title = ko.observable("@Model.Title");
                this.firstName = ko.observable("@Model.FirstName");
                this.lastName = ko.observable("@Model.LastName");

            this.fullName = ko.computed(function () {
                return this.title() + " " +  this.firstName() + " " + this.lastName();
            }, this);

        }

         @{
             var jsList = Html.Raw(JsonConvert.SerializeObject(ViewBag.Countries));
         }

        function newViewModel() {
            var theAppViewModel = new AppViewModel()
            var g = ko.mapping.fromJS(theAppViewModel);

            var viewModel = { vm: ko.observable([]) }
            viewModel.vm = ko.mapping.fromJS(@jsList);

            ko.applyBindings(g);
        }

        // Activates knockout.js
        $(document).ready(function () {
            ko.applyBindings(new newViewModel());
        });

<ul style="list-style-type: none; float: left; margin-top: 20px; ">
    <li>
        @Html.LabelFor(model => model.Title)
        <input data-bind="value: title"/>
    </li>
    <li>
        @Html.LabelFor(model => model.FirstName)
        <input data-bind="value: firstName" />
    </li>
    <li>
        @Html.LabelFor(model => model.LastName)
        <input data-bind="value: lastName" />
    </li>

    <li>
        Full Name
        <Span data-bind="text: fullName"></Span>
    </li>

    <li>
        Coutries:
        <select data-bind="foreach: vm">

                <option data-bind="text: CountryName"></option>

        </select>
    </li>      

</ul>

My Controller has this on it,

 public ActionResult Index()
        {
            //ViewBag.Message = "KO js in mvc 4";
        ViewBag.Countries = new List<Country>(){
            new Country()
            {
                Id = 1,
                CountryName = "America",
                Abbreviation = "USA"
            },
            new Country()
            {
                Id = 2,
                CountryName = "United Kingdon",
                Abbreviation = "UK"
            },
            new Country()
            {
                Id = 3,
                CountryName = "Irland",
                Abbreviation = "IRL",
            }
        };

        var vm = new PersonViewModel()
        {
            Id = 1,                
            DateOfBirth = new DateTime(1993, 01, 22),

            Title = "Miss",
            FirstName = "Jamie",
            LastName = "Oscar",
        };

        return View(vm);
    }

I can return the List from the controller in a standard loop like this:

        <select>
            @foreach(var c in ViewBag.Countries)
            {
                <option>@c.CountryName</option>
            }
        </select>

But I would like to bind the results to the list Via Knockout.js.

Upvotes: 2

Views: 2628

Answers (2)

AlanMorton2.0
AlanMorton2.0

Reputation: 1053

it has now come to my attention that I can now bind knockout Json result to a @html.DropDownListFor attribute helper and still bind my data from knockout I have a DropDown list that is populated by knockout json array object, but then also bind this to the MVC 4 model this can be then used in the controller and the passed back to WCF or Linq to SQL for database

@Html.DropDownListFor(m => m.SelectedAuthType, 
        (SelectList)Model.authlevellistItems, 
new { id = "alddl", data_bind = " options: Countries, optionsText: 'CountryName', optionsValue: 'Id'" })

works perfectly with models now as well as JSON knockout results.

Upvotes: 0

haim770
haim770

Reputation: 49123

Your current viewModel that is containing the countries list is not bound, the only bound View-Model is the g you're calling applyBinding() with. Also, there's no point calling applyBinding() twice (on the same element).

Try this instead:

$(document).ready(function() {
    var vm = new AppViewModel();
    vm.Countries = ko.mapping.fromJS(@jsList);
    ko.applyBindings(vm);
});

<select data-bind="value: countryId,
                   options: Countries,
                   optionsText: 'CountryName',
                   optionsValue: 'Id'"></select>

Please keep in mind that the value directive is referring to the chosen CountryId of the person but you currently don't have such a field in your View-Model.

Consider adding it as well:

var vm = new PersonViewModel()
        {
        Id = 1,                
        DateOfBirth = new DateTime(1993, 01, 22),
        Title = "Miss",
        FirstName = "Jamie",
        LastName = "Oscar",
        CountryId = 1
        };

function AppViewModel() {
      this.title = ko.observable("@Model.Title");
      this.firstName = ko.observable("@Model.FirstName");
      this.lastName = ko.observable("@Model.LastName");
      this.countryId = ko.observable(@Model.CountryId);
      }

Upvotes: 1

Related Questions