How to enable data binding in KnockoutJS using the ASP.NET MVC 3 "Razor" View Engine? - asp.net-mvc-3

I'm trying to implement this Knockout example using ASP MVC 3's "Razor" view engine.
The first topic covers simple data binding of a C# array using the standard ASP view engine. I am trying the sample example using "Razor", and this line:
<script type="text/javascript">
var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;
</script>
results in an empty variable for initialData.
I also tried this:
#{
string data = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model);
}
And then specified the initialData like this:
var initialData = #Html.Raw(data);
This populates initialData with the dataset, but binding does not work.
I'm just trying to databind this set in order to display a count of the ideas, as in the example:
<p>You have asked for <span data-bind="text: gifts().length"> </span> gift(s)</p>
Why isn't data binding working in this instance?

The easiest way in MVC3 is to do:
var initialData = #Html.Raw(Json.Encode(Model));

I ran into this same problem, and discovered that it was my own stupidity that caused the issue (which it so often is). I forgot to wait until the DOM loaded to call ko.applyBindings(viewModel) - so simply using:
$(document).ready(function () { ko.applyBindings(viewModel); });
So the whole script as
<script type="text/javascript">
var initialData = #Html.Raw( new JavaScriptSerializer().Serialize(Model));
var viewModel = {
gifts: ko.observableArray(initialData)
};
$(document).ready(function () { ko.applyBindings(viewModel); });
</script>
This worked with knockout-1.2.1.js and jquery-1.5.1.js

Related

How to declare a variable with razor syntax within javascript block for a razor view?

I have created a razor view (Demo.cshtml) and I tried to declare razor variable within javascript block as shown below:
Code:
#{
ViewBag.Title = "Demo";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>
Demo</h2>
<script type="text/javascript">
$(function () {
#{
bool test = true;
}
});
</script>
I am getting few warnings as mentioned below:
Warning 1 Invalid character Demo.cshtml 10 10
Warning 2 Expected ';' Demo.cshtml 11 18
Can anyone guide me in resolving the above warning?
Well its not so easy to explain. For different needs you can use different solutions.
The easiest way is to use 'text' tag:
<script type="text/javascript">
#{
<text>
alert(#myVar);
</text>
}
</script>
And for example for String values you can do like
<script type="text/javascript">
var url = '#Url.RouteUrl("admin", new { controller = "users"})';
</script>
For boolean types you can do like in this example, but it looks like a stupid hack :)
var bool = '#ViewData.ModelState.IsValid' == "True";
And for collections you need to implement some helper method to be able to call
var myArray = #Html.ToJson(MyCSharpCollectionObject)

Ember event in one view update another?

I have a small extract from my Ember app here. My page contains a number of views each containing different data each with their own controllers.
I want a search field (in index view) to go in one view which should "talk" to the stationList controller to update the content of the stationList view. This doesn't work. I get an error: TypeError: this.get(...).search is not a function
The logging outputs the name of the contoller I've asked it to use: App.StationListController
I added a second search form inside on the StationList View. This one works just fine. The logging this time outputs a dump of the StationListController object. So I am guessing that the other search form, despite my code (in SearchFormView): controllerBinding : 'App.StationListController', is not correctly setting the controller.
So I guess my question is why not?
How can I route the change on the form field in the one view to call a funciton on another view's controller?
Here's my code:
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<div id="searchForm">search form view search:
{{#view App.SearchFormView}}
{{view App.StationSearchField}}
{{/view}}
</div>
<div id="stationList">{{render stationList}}</div>
</script>
<script type="text/x-handlebars" data-template-name="stationList">
station list view search: {{view App.StationSearchField}}
<ul>
<li>List</li>
<li>will</li>
<li>go</li>
<li>here</li>
</ul>
{{searchTerm}}
</script>
And
App = Ember.Application.create({})
App.SearchFormView = Ember.View.extend({
init : function()
{
console.log("SearchFormView init", this.get('controller'))
}
})
App.StationSearchField = Ember.TextField.extend({
keyUp: function(event) {
var searchTerm = this.value
console.log("value",searchTerm,this.get('controller'))
this.get('controller').search(searchTerm)
}
})
App.StationListController = Ember.ArrayController.extend({
content : [],
searchTerm : null,
search : function(term)
{
this.set("searchTerm",term)
console.log("searching",term)
}
});
Fiddle: http://jsfiddle.net/ianbale/8QbrK/14/
I think the controllerBinding stuff is from the older version, I don't think that works anymore.
You can use controllerFor on get('controller') in the StationSearchField.
this.get('controller').controllerFor('station_list').search(searchTerm)
But controllerFor is deprecated and may be removed. Depending on your application structure you use needs on the controller.
Another way which I am using, is to send a custom event from the View, which the Route then sends to the corresponding controller.
App.IndexRoute = Ember.Route.extend({
events: {
search: function(term) {
controller = this.controllerFor('station_list')
controller.search(term);
}
}
});
and dispatch a search event from view like so.
this.get('controller').send('search', searchTerm);
The advantage of this method is you dispatch the same event from multiple places and it would get handled in the same way.
Here's the updated jsfiddle.

cshtml/vbhtml and the new # to include server side data, but without encoding?

I started to learn MVC and in conjunction want to use the KnockOut.js
I am having trouble understanding why the new # include tag encodes everything to HTML(edit: ok i know now to prevent XSS).. but even worse how to stop it from doing that..
I have this code.
#{
ViewBag.Title = "Home Page";
var myData = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model);
}
<script type="text/javascript">
var initialData = #myData ;
Which produces this source
<script type="text/javascript">
var initialData = [{"Title":"Tall Hat","Price":49.95},{"Title":"Long Cloak","Price":78.25}] ;
Ok. so tried using HttpUtility.HtmlDecode.. and nothing happens on the included bit in the javascript because the razor engine is reencoding it? but if it use the encode then reecnodes the encodes html.. briallinat.
I cannot work out how to stop the encoding.
The msdn says use #: but that does not work in the javascript block, i even tried
#{ #:new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model);}
That just something wierd and causes other errors.
How should this be done in the MVC model?
In aspx using
var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;
works fine..
Html.Raw(string) will write out your string in its raw, unencoded form. Provided your string is not encoded to begin with.
code example as requested (?!?!)
#{
ViewBag.Title = "Home Page";
var myData = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model);
}
<script type="text/javascript">
var initialData = #Html.Raw(myData) ;
MVC (or the Razor view engine in this case) encodes all your strings as a HTML string using the MvcHtmlString by default. To get around it, use:
<script type="text/javascript">
var initialData = "#MvcHtmlString.Create(myData)";
</script>
This then assumes your string has already been encoded.

Equivalent Razor Syntax of Following Statement?

Let's say I have following ASP.NET Web Form engine code, how can I express it in Razor engine?
<script type="text/javascript">
var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;
</script>
Thanks
Hardy
I would use the following:
<script type="text/javascript">
var initialData = #Html.Raw(new JavaScriptSerializer().Serialize(Model));
</script>
This is exactly the same as your example (note the Html.Raw).
If you want the output (html)encoded or your code returns an IHtmlString :
<script type="text/javascript">
var initialData = #(new JavaScriptSerializer().Serialize(Model));
</script>
You do want to use #( ... ) syntax, because using #new JavaScriptSerializer(..) will let the Razor parser stop at the first space (after new).
The syntax like this:
<script type="text/javascript">
var initialData = #{ new JavaScriptSerializer().Serialize(Model); }; #* <== wrong *#
</script>
does not work because it will call new JavaScriptSerializer, but discard the output.

Using Jquery in Controller Page-ASP.NET MVC-3

Could any one give an example, how to use Jquery in Controller Page. MVC3 -ASP.NET(How To put various tags like )
I want to show a simple alert before rendering a view in Controller.
Thank you.
Hari Gillala
Normally scripts are part of the views. Controllers shouldn't be tied to javascript. So inside a view you use the <script> tag where you put javascript. So for example if you wanted to show an alert just before rendering a view you could put the following in the <head> section of this view:
<script type="text/javascript">
alert('simple alert');
</script>
As far as jQuery is concerned, it usually is used to manipulate the DOM so you would wrap all DOM manipulation functions in a document.ready (unless you include this script tag at the end, just before closing the <body>):
<script type="text/javascript">
$(function() {
// ... put your jQuery code here
});
</script>
If you are talking about rendering partial views with AJAX that's another matter. You could have a link on some page that is pointing to a controller action:
#Html.ActionLink("click me", "someAction", null, new { id = "mylink" })
and a div container somewhere on the page:
<div id="result"></div>
Now you could unobtrusively AJAXify this link and inject the resulting HTML into the div:
$(function() {
$('#mylink').click(function() {
$('#result').load(this.href, function() {
alert('AJAX request finished => displaying results in the div');
});
return false;
});
});

Resources