0
votes

I use ko.mapping utility to bind my mvc model to knockoutjs. My mvc model is this

  public class Person
  {
    public string Name { get; set; }
    public string Surname { get; set; }
    public Achievement[] achievements { get; set; }
  }

  public class Achievement
  {
     public string Title { get; set; }
     public int Score { get; set; }
  }


  public ActionResult Index()
  {
     Person person = new Person
     {
        Name = "Name",
        Surname = "Surname",

        achievements = new Achievement[]
        {
           new Achievement { Title="Ach 1", Score=10 },
           new Achievement { Title="Ach 2", Score=11 },
           new Achievement { Title="Ach 3", Score=12 },
        }
     };
     return View(person);
  }

I want my javascript model to contain some additional properties both in Person and Achievement objects so I use knockout mapping plugin and write only the new properties in javascript (Person.fullName and Achievement.Message).

@{
    string theData = new JavaScriptSerializer().Serialize(Model);
 }
  <div>
    <div><label>Name </label> <span data-bind="text:Name"></span></div>
    <div> <label>Surname </label> <span data-bind="text:Surname"></span> </div>
    <div> <label>Full Name </label> <span data-bind="text:fullName"></span></div>

    <ul data-bind="foreach:achievements">
        <li>
            <span data-bind="value:Title" />
            <span data-bind="text:Score"></span>
            <span data-bind="text:Message"></span>
        </li>
    </ul>
</div>
<script type="text/javascript">
    personViewModel = function (data) {
        var self = this;
        ko.mapping.fromJS(data, {}, self);  
        self.fullName = ko.computed(function () {
            return self.Name() + "   " + self.Surname();
        });
    }

    achievement = function (data) {
        var self = this;
        ko.mapping.fromJS(data, {}, self);

        self.Message = ko.computed(function () {
            return self.Title() + "  " + self.Score();
        });
    }
    ko.applyBindings(new personViewModel(@Html.Raw(theData)));
</script>

The problem is that achievement class is not mapped at all. What is the right way to load data from MVC controller without writing twice the model in c# and in javascript.

1

1 Answers

0
votes

You can try something like this:

var custMap = {};

custMap['achievements'] = {
 create: function(data) {
  var result = [];
  for(var i = 0; i < data.length; i++){
   result.push(new achievement(data[i]);
  }
  return new ko.observableArray(result);
 }
}

And to map it:

ko.mapping.fromJS(data, custMap, self);