3

I'm having a problem mapping a JSON array generated by .NET JavaScriptSerializer, to knockout.js. The array is generated like this (shortened for ease):

OrderProposalFacade[] proposals = new OrderProposalFacade[order.OrderProposals.Count];

foreach (OrderProposal proposal in order.OrderProposals)
{
    proposals[i++] = new OrderProposalFacade(proposal);
}

ViewBag.OrderProposals = new JavaScriptSerializer().Serialize(proposals);

The generated JSON string is something like this:

[{ "ProposalId":1,"ProgrammedWeek":null,
   "ProposalValue":120,"ProposalValueCorrected":130,
   "ProposalDateSent":"01-12-2011","ProposalDateCorrected":"01-12-2011",
   "ServiceId":1,"ServiceDescriptiveId":"OS001","ProposalState":2
 },
 {//another similar object}
]

On the ASP.NET MVC view I do this in order to bind the array:

var initialData = ko.mapping.fromJSON(<%: new HtmlString(ViewBag.OrderProposals as string) %>);
var viewModel = {
    proposals: ko.observableArray(initialData),
    //some methods; removed to ease reading
};
ko.applyBindings(viewModel);

The problem: the proposals array is supposed to be rendered by a knockout.js template, but nothing is rendered. Using Firebug I don't see any objects on the initialData array, so I presume there is an error while initializing it and, therefore, proposals. The binding to the template is like this:

<div id="service-orders" data-bind='template: { name: "proposal-template", foreach: proposals }' style="margin:0 -.7em 0 -0.5em;"></div>

If I remove ko.mapping.fromJSON() everything works fine, i.e., the template is rendered with the values on the proposals array. But another problem arises when I update a value of an object on the initialData array. On my understanding if I update an observable property, the template is rendered again (therefore the knockout.js mapping), but without mapping all properties it won't happen, right?

In short, I need to map all the properties on the initialData array in order to make them observable to update my view when I change a value of one of it's objects, but it isn't working.

Any ideas? Thank you in advance!

4
  • for a start why are you using HtmlString? simple <%:ViewBag.OrderProposals %> should suffice. Secondly, changing value of any item in the observableArray will not render the template again. observableArray only observes the addition/deletion in the array and not modifications in it's individual items. Commented Dec 1, 2011 at 18:02
  • @nEEbz: ok, the assumption I made was wrong. How can I detect a change? shall I use updateFromJS? Commented Dec 1, 2011 at 19:12
  • Isn't ko.mapping.fromJSON(<%: PROPOSAL STUFF %>); completely statically rendered/generated inline by ASP? In other words, ko.mapping.fromJSON isn't needed at 'compile' time, i.e. you only need it if you were populating intialdata dynamically at runtime. Commented Dec 2, 2011 at 7:30
  • you probably shouldn't use the : in there either, but stick to = as you don't want it to be escaped, the serialiser has already done it for you. Commented Dec 4, 2011 at 5:05

1 Answer 1

5

Finally solved it! The final Javascript is like this:

var initialData = <%: new HtmlString(ViewBag.OrderProposals as string) %>;
var viewModel = {
    proposals: ko.observableArray(),
    //some methods; removed to ease reading
};

viewModel.proposals = ko.mapping.fromJS(initialData);

ko.applyBindings(viewModel);

The 2 changes I made:

  • instead of ko.mapping.fromJSON(initialData) I call ko.mapping.fromJS(initialData). Not shure, but I it seems that .fromJSON() has some problem mapping the array I putted on the question;
  • the .fromJS() method is invoked after the viewModel creation.
Sign up to request clarification or add additional context in comments.

1 Comment

I think fromJSON don't work because when you create your javascript string from an HtmlString, you receive a string without encoding and this is considered as a valid Javascript object but not a valid JSON. To have a valid JSON object, you will need to not use the HtmlString but in this case, you will have a couple of problems with some invalids characaters to parse. I think the only reason to use fromJSON is when you make an ajax call that returns a valid JSON stream from the server. Another way could be to convert your initialData to JSON.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.