Knockout Mapping attempt not mapping with JSON responses - asp.net-mvc

I am new to knockout and cannot seem to get a simple mapping to work at all. I am in an MVC4 C#.
My View looks like such:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Index";
}
<h2>Simple Mapping Example</h2>
The time on the server is: <span data-bind="text: ServerTime"></span>
and <span data-bind="text: NumberOfUsersConnected"></span> user(s) are connected.
#section Scripts
{
<script type="text/javascript">
function ViewModel() {
var self = this;
self.ServerTime = ko.observable();
self.NumberOfUsersConnected = ko.observable();
}
var vm = new ViewModel();
ko.applyBindings(vm);
$.getJSON('/Mapping/GetServerInfo', function(data) {
ko.mapping.fromJSON(data, {}, vm);
});
</script>
}
Example JSON that is returned from the controller call 'Mapping/GetServerInfo' is:
{"ServerTime":"2013-03-13T14:24:10.5675104-07:00","NumberOfUsersConnected":5}
For the data-binds I have tried text and value, neither one causes any data to be bound and displayed.
Am I missing something really obvious?
As per the question in the comments yes this is what is in my Layout.
<script type="text/javascript" src="~/Scripts/knockout-2.2.1.js"></script>
<script type="text/javascript" src="~/Scripts/knockout.mapping-latest.js"></script>
Thanks

From the $.getJSON documentation
The success callback is passed the returned data, which is typically a
JavaScript object or array as defined by the JSON structure and parsed
using the $.parseJSON() method.
So your the data variable is holding an already parsed object so you need to use the ko.mapping.fromJS method:
$.getJSON('/Mapping/GetServerInfo', function(data) {
ko.mapping.fromJS(data, {}, vm);
});

Related

How KnockoutJS Mapping plugin works

here i got a sample code which said KnockoutJS Mapping plugin automatically bind UI.
here is code
<script src="~/Scripts/knockout.mapping-latest.js"></script>
<script type="text/javascript">
$(function() {
var viewModel = ko.mapping.fromJS(#Html.Raw(Model.ToJson()));
ko.applyBindings(viewModel);
});
</script>
suppose my html binding as follows
<p>First name: <strong data-bind="text: firstName"></strong></p>
<p>Last name: <strong data-bind="text: lastName"></strong></p>
and my server side model return json like
{fname:Josh;lname:Steve};
so here my question is how KnockoutJS Mapping plugin could understand that fname value need to map to databinding firstName & lname need to map to databinding lastName ?
am i clear what i am trying to say. so guide me in this case how one could bind json to html UI through KnockoutJS Mapping plugin.
in this situation KnockoutJS Mapping plugin would be right choice or not ?
do i need to bind manually by viewmode like
First name:
Last name:
json as follows var person = {fname:Josh;lname:Steve};
var viewModel = function(person) {
this.firstname= ko.observable(person.fname);
this.lastname= ko.observable(person.lname);
};
ko.applyBindings(new viewModel(person));
As requested in the comment I put this as a possible answer.
If you have model with many properties and want only some of them to map to different names, this is the way to do it:
var viewModel = ko.mapping.fromJS(#Html.Raw(Model.ToJson()));
var extendViewModel = function () {
this.firstName = ko.computed({
read: function(){
return viewModel.fname();
},
write: function(value){
viewModel.fname(value);
},
owner: viewModel
});
};
viewModel = ko.mapping.fromJS(new extendViewModel(), viewModel);
ko.applyBindings(viewModel);
Then you can use firstName in your markup for bindings and viewModel.fname will be updated, too.

Problems using the Razor model when creating my knockout ViewModel

I'm having problems with using the Model in a javascript call when setting up my knockout VM..
#model List<AdminGui.Models.Domain>
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js" type="text/javascript"></script>
<script type="text/javascript">
function ViewModel() {
var self = this;
self.domains = ko.observableArray(
ko.utils.arrayMap(#Model, function(item) {
return new Domain(item.guid, item.description, item.namespaces);
}));
}
I get a syntax error on #Model in the ko.utils.arrayMap call. I suspect it might be my Razor-fu that is lacking... :)
The Model is your C# model which cannot be used directly from JavaScript, because writing #Model just calls ToString on it which is not what you need.
What you need is to convert your Model to JSON, you can do this with the Json.Encode method
self.domains = ko.observableArray(
ko.utils.arrayMap(#Html.Raw(Json.Encode(Model)), function(item) {
return new Domain(item.guid, item.description, item.namespaces);
}));
Note: You need to wrap it with Html.Raw to turn off the automatic HTML Encoding in Razor.

Knockoutjs binding JSON

I am have a problem binding a JSON result with knockout js. Below is my code
var AddDeparmentViewModel = function() {
var self = this;
self.AddDepartmentModel = {};
$.getJSON('/EventTracker/Department/GetEmptyModel/', function(data) {
ko.mapping.fromJS(data, {}, self.AddDepartmentModel);
});
};
$(document).ready(function() {
var departmentViewModel = new AddDeparmentViewModel();
ko.applyBindings(departmentViewModel);
})
Here is my HTML:
<div class="titleWrapper">
Add Department
</div>
<label>Department Name:</label>
<input data-bind="value: AddDepartmentModel.DepartmentName" id="departmentNameTextbox" type="text" />
<p data-bind="text: AddDepartmentModel.DepartmentName"></p>
The values I am returning are not appearing. Could someone point out where my mistake is. In this case the server is returning a single object not an array of objects.
Thanks!
Edit:
The Server returns this JSON:
{"DepartmentID":0,"DepartmentName":"Test","EVNTTRKR_Admins":[],"EVNTTRKR_Event": [],"EVNTTRKR_ItemCategories":[]}
Edit:
Here is the function GetEmptyModel:
public JsonResult GetEmptyModel()
{
var eventT = new EVNTTRKR_Departments();
eventT.DepartmentName = "Test";
return Json(eventT, JsonRequestBehavior.AllowGet);
}
The problem you are having seems to be fairly common. You are creating observables after binding the viewmodel. When this happens there is nothing for knockout to hook into and nothing gets rendered. A fix for this would be to make sure AddDepartmentModel is an observable and to set it to the return value rather than overwritting it with the fromJS.
var AddDeparmentViewModel = function() {
var self = this;
self.AddDepartmentModel = ko.observable({}); //important to have a default value so bindings dont break
$.getJSON('/echo/json/', function(data){
var mapped = ko.mapping.fromJS(data);
self.AddDepartmentModel(data); // here we are pushing values into the observable
});
};
This also requires fixes to the bindings as they now need to invoke AddDepartmentModel as a function:
<input data-bind="value: AddDepartmentModel().DepartmentName" id="departmentNameTextbox" type="text" />
Example fiddle with json request and population in callback.
http://jsfiddle.net/infiniteloops/YWC9N/
I created a jsfiddle here and replaced your getJson call with your server data (because I cannot call your getJson url). And it all seems to work which leads me to believe that an error is occuring in the getJson call.
Could you open your browser developer tools and look for any errors in the console. If there is an error and you're not sure what it means, add the error information to your original problem description.
var AddDeparmentViewModel = function() {
var self = this;
self.AddDepartmentModel = {};
var data =
{"DepartmentID":0,"DepartmentName":"Test","EVNTTRKR_Admins":[],"EVNTTRKR_Event": [],"EVNTTRKR_ItemCategories":[]
};
ko.mapping.fromJS(data, {}, self.AddDepartmentModel);
};
$(document).ready(function() {
var departmentViewModel = new AddDeparmentViewModel();
ko.applyBindings(departmentViewModel);
})

How to use Knockout.js in asp.net mvc Razor correctly and sufficiently?

i try to learn knockout.js on asp.net mvc razor. i have been coding below code to learn and test myself
But View side throws me a js error.
Error occurs on "var model = #Html.Raw(Json.Encode(Model));" Error : Microsoft JScript run-time error: 'fromJSON' Unable to get value of the property: the object is empty or undefined
Controllers:
[HttpGet]
public ActionResult GetGift()
{
GiftModel gift = new GiftModel();
gift.Price = 120;
gift.Title = "Test";
return View(gift);
}
View:
#using System.Web.Script.Serialization;
#model knockout1.Models.GiftModel
#{
ViewBag.Title = "GetGift";
}
<h2>GetGift</h2>
<script src="/Scripts/knockout-2.1.0.js" type="text/javascript"></script>
<script type="text/javascript">
var initialData = #Html.Raw( new JavaScriptSerializer().Serialize(Model));
var viewModel = ko.mapping.fromJSON(initialData);
$(document).ready(function () { ko.applyBindings(viewModel); });
</script>
<p>Title: <strong data-bind="text: Title"></strong></p>
<p>Price: <strong data-bind="text: Price"></strong></p>
But i changed my js codes. Error disappears. i can not understand first usage why doesn't correct? i readed Darin Dimitrov's response:
Darin Dimitrov :
<script type="text/javascript">
var jsonResultData = #Html.Raw(Json.Encode(Model));
</script>
Me: (it is working good.)
<script type="text/javascript">
$(function()
{
var model = #Html.Raw(Json.Encode(Model));
// Activates knockout.js
ko.applyBindings(model);
});
</script>
Based on the error message
'fromJSON' Unable to get value of the property: the object is empty or undefined
and page setup your problem is that you are trying to use the KO mapping plugin without including the plugin.
All the methods which are string with ko.mapping are part of the mapping plugin and for using them you need to refeence the knockout.mapping.js file in your HTML page.
Can you can download mapping plugin from github

SPA Knockout JS Filter

I developed MVC 4 Single Page Application using ADO.Net as a data source. Trying to filter the view by ID, tried session variables without any luck. Here is the view code:
<script type="text/javascript" src="#Url.Content("~/Scripts/BloodPressuresViewModel.js")"></script>
<script type="text/javascript">
$(function () {
upshot.metadata(#(Html.Metadata<KOTest2.Controllers.DALController>()));
var viewModel = new MyApp.BloodPressuresViewModel({
serviceUrl: "#Url.Content("~/api/DAL")"
});
ko.applyBindings(viewModel);
});
</script>
and hee is the calss code in the Javascript file:
.....
var entityType = "BloodPressure:#KOTest2.Models";
MyApp.BloodPressure = function (data) {
var self = this;
// Underlying data
self.ID = ko.observable(data.ID);
self.PHN = ko.observable(data.PHN);
self.Day = ko.observable(data.Day);
self.Systolic = ko.observable(data.Systolic);
self.Diastolic = ko.observable(data.Diastolic);
self.HeartRate = ko.observable(data.HeartRate);
upshot.addEntityProperties(self, entityType);
}
.....
I think the best solution is to pass the ID using ViewBag to the view from the controller. Any idea how I can do that!!
Since I am not experienced programmer, will it be possible to filter (foreach)
<tbody data-bind="foreach: bloodPressures">
Thanks in advance.
I am not sure I understand how you access the database (on the server, right?) to do the filtering, but you could do something like this:
<table data-bind="foreach: rows">
<tr>
<td>id: <span data-bind="text: ID"></span></td>
<td>PHN: <span data-bind="text: PHN"></span></td>
....
</tr>
</table>
and in your javascript
function viewModel() {
var self = this;
this.loggedIn = ko.observable(false);
this.rows = ko.observableArray([]);
// return an array of objects to display to the user
function getDataFromServer() {
return ...;
}
ko.computed(function() {
if (this.loggedIn())
this.rows(getDataFromServer());
},this);
...
}
However you do your authentication, after it succeeds, execute this.loggedIn(true) which will cause the computed function to trigger the pull from the server and the setting of the this.rows(); this in turn will update the display.

Resources