How can i use model in Javascript? - c#

Example :
<script type="text/javascript">
function abc() {
var t = document.getElementById("name").value;
#foreach(Player pl in Model){
if (t == pl.Name) {
alert("This name is already use!");
}
}
</script>
Error : t - cannot resolve symbol
How can i use JavaScript variable in C# code? Is it possible in this example?

You cannot use JS variables in C# code , but you can use C# variables in the code.
In most cases C# is used to render HTML or JS.
In your case it would be best if you render your C# serverside model as a JS array , which you can later on iterate.
make an action that returns your list (assuming it's a list) as
a JSON
fetch the data with an AJAX get call to your action.
Cheers!

You may do something like this.
<script type="text/javascript">
function abc(players) {
var t = document.getElementById("name").value;
for(p in players) {
if (t == p.Name) {
alert("This name is already use!");
}
}
abc(#Html.Raw(Json.Encode( Model )));
</script>

Related

Url.Action and two variables

I have #Html.PagedListPager(Model, page => Url.Action("GetTabData", new { page })
and inside my js file I have ready to use myTab variable which I need to send together with page in above example.
How can I do that?
Update:
I'm using js variable to determine which tab is user click and based on that value I'm quering data. Now I have implemeted pagination which uses above generated link. With this in place my ajax call for sending activeTab is broken, I need to send this value together with page inside above Url.Action.
This is js variable which I use to send over ajax to determine which tab is user click
$(function () {
var activeTab = null;
$('#tabs .tabLink').click(function (event) {
var activeTab = $(this).attr('href').split('-')[1];
GetTabData(activeTab);
});
GetTabData(ommitted on purpse)
});
I don't get the question clearly, but I am taking a guess here. Don't know if this is what you are looking for.
Note - You have GetTabData in both your javascript as well as cshtml code, I am hoping this is just coincidence, because the js function cannot be invoked via #Url.Action in this manner.
If you need to send two values as part of your URL, you could do it either in a RESTful way or have querystrings.
Option 1 -
Url.Action("GetTabData", new { page=2, tab="blah" })
Your corresponding controller action would look like
public ActionResult GetTabData(int page, string tab)
{
...
}
Option 2 -
create a querystring and append it to the URL
/GetTabData?page=2&tab=blah
In this case the controller action would look like this
public ActionResult GetTabData()
{
var params = Request.QueryString;
...
}

Set a javascript variable from mvc controller

Is it possible to set a javascript variable from a c# controller? We have a situation where we override our master page with a dumb downed version that doesn't require login for users. However, our javascript timeout timer still runs. I would like to in the controller method that overrides the master, to override the timeout to something huge.
public dumbDownController()
{
ViewData["MasterPageOverride"] = "~/Views/Shared/_NoLogin.cshtml";
//Somehow reset that timer below from 20 to like 9999. To simulate no timeout.
return View("Cities", model);
}
Then our javascript file has.
tb.sessionTimer = (function () {
var SESSION_TIMEOUT = 20;
var currentTimeoutCounter = SESSION_TIMEOUT * 60;
...
lots more irrelevant to question
...
}
Large app, so looking to barely change the javascript. Would like to handle it from the controller.
Short Answer:
<script>
var xyz = #ViewData["MasterPageOverride"];
</script>
Longer Answer:
You can't directly assign JavaScript variables in the Controller, but in the View you can output JavaScript which can do the same.
You need to pass the variable to the View somehow. For this example I'll use the ViewData object dictionary. You can set an element in the Controller:
public ActionResult SomeAction()
{
ViewData["aNumber"] = 24;
}
Then in the View it is possible to use it as:
<script>
var xyz = #ViewData["aNumber"];
</script>
Which will be sent to the client browser as:
<script>
var xyz = 24;
</script>
Strings need a bit more attention, since you need to enclose them between '' or "":
<script>
var xyz = "#ViewData["aString"]";
</script>
And as #Graham mentioned in the comments, if the string happens to be valid JSON (or any object literal, but it is very easy to create JSON), and you want to use it as a JavaScript object, you can:
<script>
var xyz = #ViewData["aJsonString"];
</script>
Just make sure the output is valid JavaScript.
On a footnote, be careful with special HTML characters, like < as they are automatically HTML-encoded to prevent XSS attacks, and since you are outputting JavaScript not HTML, this can mess things up. To prevent this, you can use Html.Raw() like:
<script>
var xyz = #Html.Raw(ViewData["aJsonString"]);
</script>
If tb is within the scope of your controller, consider just overriding the sessionTimer function:
public dumbDownController(){
...
tb.sessionTimer = function(){return false;}
}
You have two options (as I understand):
Create the variable from viewbag, data, tempdata, like so:
var SESSION_TIMEOUT = #ViewData["MasterPageOverride"];
var SESSION_TIMEOUT = #ViewBag["MasterPageOverride"];
var SESSION_TIMEOUT = #TempData["MasterPageOverride"];
Or, do it via jQuery AJAX:
$.ajax({
url: '/YourController/YourAction',
type: 'post',
data: { id: id },
dataType: 'json',
success: function (result) {
// setVar
}
});

How to pass an object from a mvc controller action to a view using jquery

Can someone help me out I'm new to jQuery, I would like to know how can I pass an object through from a controller action MVC
public ActionResult UserGroupSetting()
{
UserGroupSetting setting = //some code to retrieve the settings
ViewData["Theme"] = setting.Theme;
ViewData["Image"] = setting.LogoImage;
returnView(setting);
}
What I want its to get the Theme and the logo image, in a jQuery function, that I will use to update a class in a stylesheet, The theme object contains a colour in Hex form only for now.
If someone can please help me with the call to a jquery function and how will I expose both the image and the theme objects in jquery.. Thanks
You can return the data in jSon format and let jquery make a call to your action method with getJSON method
public ActionResult UserGroupSetting()
{
var result=new { Theme="YourTheme", Logo="YourLogoURL"};
return Json(result, JsonRequestBehavior.AllowGet);
}
In your page,Call this from your javascript
$(function(){
$.getJSON('YourController/UserGroupSetting', function(data) {
alert(data.Theme);
alert(data.Logo);
});
});
if i were you , i would do this:
you can use ViewBag: in action: ViewBag.Setting = setting;
UserGroupSetting setting = //some code to retrieve the settings
ViewBag.Theme = setting.Theme;
ViewData.Image = setting.LogoImage;
returnView(setting);
then in Razor:
#{
var setting = (UserGroupSetting)ViewBag.Setting;
}
output it to javascript tag:
<script type="text/javascript">
var setting = new setting{
Theme = #setting.Theme,
Image = #setting.Image
}
</script>
This may not be the best solution, but one option I've used in the past is to create a hidden input in your view and access the value of the input in your jQuery code. This would be an example of the code you would have in your view:
<input id="someID" type="hidden" value="#TempData["Theme"]" />

Creating a ActionLink that works with a javascript function

I have a datatable, on that datatable i set a Html.ActionLink. When I click that action link, I want to send an id of the item to a javascript function and have a new datatable appear below with all of its content that belongs to the selected item in the datatable above. So for example if I click a students name in a table, I want all the students Grades and Test to appear below in a separate datatable. I've never worked with javascript much so I'm not sure how I can do this. If someone can please point me in the right direction or give some tips I'd appreciate it.
original first datatable:
#foreach (var item in ((List<Epic>) ViewData["selectedestimate"]))
{
<tr>
<td>
#* #Html.ActionLink(#item.Name, "action", "controller", new {id = item})*#
#item.Name
</td>
Javascript to call:
<script type="text/javascript">
function StoryClick(story) {
$.get("#Url.Action("action", "controller")", function (response) {
$('#stories').accordion({ collapsible: true });
});
}
</script>
ActionController:
public List<EpicDetails> getEpicDetails(int id)
{
return eRepository.getItemsById(id).tolist();
}
Or do I need an ActionResult?
public Actionresult Details(int id)
{
}
I realize that I'm not even close right now, but its just b/c I'm not sure what steps to take to do this.
Eventually I would make a accordion and put the table in the accordion.
In situations like this I like to actually keep the <a> the ActionLink generates, and just add JavaScript to enhance the behavior of the link. So your view wouldn't really change (I did add a class so that we can bind an event handler to it later):
#Html.ActionLink(#item.Name, "action", "controller", new {id = item, #class = "item-link" })
Then write some jQuery (it looks like you already have a dependency on jQuery. If not, I can revise the answer to use vanilla JavaScript) to bind an event handler to links with class item-link:
<script type="text/javascript">
$(document).ready(function () {
$("a.item-link").click(function (event) {
event.preventDefault(); // Stop the browser from redirecting as it normally would
$.get(this.href, function (response) {
// Do whatever you want with the data.
});
});
});
</script>
And, yes, your action method in the controller should return an ActionResult. It's hard for me to say what type of ActionResult you should return without actually knowing what type of data you want to consume on the client, but if you wanted to inject HTML onto the page, you could write something like this:
public ActionResult Details(int id)
{
var itemDetails = /* Get details about the item */;
return PartialView("Details", itemDetails);
}
Then in your JavaScript you would write:
$("a.item-link").click(function (event) {
event.preventDefault(); // Stop the browser from redirecting as it normally would
$.get(this.href, function (response) {
$("element_to_populate").html(response);
});
});
Where element_to_populate would be a selector that points to where you want to inject the HTML.
I would highly recommend using javascript templating (I prefer handlebars.js) on the client side and returning your student data as a JsonResult. This will keep your bandwidth usage to a minimum.
But, because you seem more comfortable with razor, you could use that for all your templates, return plain html from your controller/view, and then use this javascript instead
<script type="text/javascript">
$(function() {
$("a.item-link").click(function (event) {
event.preventDefault(); // Stop the browser from redirecting as it normally would
$("#gradesContainer").load(this.href, function (response) {
//Do whatever you want, but load will already have filled up
//#gradesContainer with the html returned from your grades view
});
});
});
</script>
In your main page, below the student list, you would just need to add
<div id="gradesContainer"></div>
Your other controller would look like this
public ActionResult TestGrades(int id) {
var model = getTestGradesModel(id);
return View(model);
}
If you were returning JSON for client-side javascript templating it would look like
public ActionResult TestGrades(int id) {
var model = getTestGradesModel(id);
return new JsonResult() {Data = model}; //no view here!
}

Access a Model property in a javascript file?

Is it possible to access a Model property in an external Javascript file?
e.g. In "somescript.js" file
var currency = '#Model.Currency';
alert(currency);
On my View
<script src="../../Scripts/somescript.js" type="text/javascript">
This doesn't appear to work, however if I put the javascript directly into the view inside script tags then it does work? This means having to put the code in the page all the time instead of loading the external script file like this:
#model MyModel;
<script lang=, type=>
var currency = '#Model.Currency';
alert(currency);
</script>
Is there any way around this?
I tackled this problem using data attributes, along with jQuery. It makes for very readable code, and without the need of partial views or running static javascript through a ViewEngine. The JavaScript file is entirely static and will be cached normally.
Index.cshtml:
#model Namespace.ViewModels.HomeIndexViewModel
<h2>
Index
</h2>
#section scripts
{
<script id="Index.js" src="~/Path/To/Index.js"
data-action-url="#Url.Action("GridData")"
data-relative-url="#Url.Content("~/Content/Images/background.png")"
data-sort-by="#Model.SortBy
data-sort-order="#Model.SortOrder
data-page="#ViewData["Page"]"
data-rows="#ViewData["Rows"]"></script>
}
Index.js:
jQuery(document).ready(function ($) {
// import all the variables from the model
var $vars = $('#Index\\.js').data();
alert($vars.page);
alert($vars.actionUrl); // Note: hyphenated names become camelCased
});
_Layout.cshtml (optional, but good habit):
<body>
<!-- html content here. scripts go to bottom of body -->
#Scripts.Render("~/bundles/js")
#RenderSection("scripts", required: false)
</body>
There is no way to implement MVC / Razor code in JS files.
You should set variable data in your HTML (in the .cshtml files), and this is conceptually OK and does not violate separation of concerns (Server-generated HTML vs. client script code) because if you think about it, these variable values are a server concern.
Take a look at this (partial but nice) workaround: Using Inline C# inside Javascript File in MVC Framework
What you could do is passing the razor tags in as a variable.
In razor File>
var currency = '#Model.Currency';
doAlert(currency);
in JS file >
function doAlert(curr){
alert(curr);
}
Try JavaScriptModel ( http://jsm.codeplex.com ):
Just add the following code to your controller action:
this.AddJavaScriptVariable("Currency", Currency);
Now you can access the variable "Currency" in JavaScript.
If this variable should be available on the hole site, put it in a filter. An example how to use JavaScriptModel from a filter can be found in the documentation.
What i did was create a js object using the Method Invocation pattern, then you can call it from the external js file. As js uses global variables, i encapsulate it to ensure no conflicts from other js libraries.
Example:
In the view
#section scripts{
<script>
var thisPage = {
variableOne: '#Model.One',
someAjaxUrl: function () { return '#Url.Action("ActionName", "ControllerName")'; }
};
</script>
#Scripts.Render("~/Scripts/PathToExternalScriptFile.js")
}
Now inside of the external page you can then get the data with a protected scope to ensure that it does not conflict with other global variables in js.
console.log('VariableOne = ' + thisPage.variableOne);
console.log('Some URL = ' + thisPage.someAjaxUrl());
Also you can wrap it inside of a Module in the external file to even make it more clash proof.
Example:
$(function () {
MyHelperModule.init(thisPage || {});
});
var MyHelperModule = (function () {
var _helperName = 'MyHelperModule';
// default values
var _settings = { debug: false, timeout:10000, intervalRate:60000};
//initialize the module
var _init = function (settings) {
// combine/replace with (thisPage/settings) passed in
_settings = $.extend(_settings, settings);
// will only display if thisPage has a debug var set to true
_write('*** DEBUGGER ENABLED ***');
// do some setup stuff
// Example to set up interval
setInterval(
function () { _someCheck(); }
, _settings.intervalRate
);
return this; // allow for chaining of calls to helper
};
// sends info to console for module
var _write = function (text, always) {
if (always !== undefined && always === true || _settings.debug === true) {
console.log(moment(new Date()).format() + ' ~ ' + _helperName + ': ' + text);
}
};
// makes the request
var _someCheck = function () {
// if needed values are in settings
if (typeof _settings.someAjaxUrl === 'function'
&& _settings.variableOne !== undefined) {
$.ajax({
dataType: 'json'
, url: _settings.someAjaxUrl()
, data: {
varOne: _settings.variableOne
}
, timeout: _settings.timeout
}).done(function (data) {
// do stuff
_write('Done');
}).fail(function (jqxhr, textStatus, error) {
_write('Fail: [' + jqxhr.status + ']', true);
}).always(function () {
_write('Always');
});
} else {// if any of the page settings don't exist
_write('The module settings do not hold all required variables....', true);
}
};
// Public calls
return {
init: _init
};
})();
You could always try RazorJs. It's pretty much solves not being able to use a model in your js files RazorJs
I had the same problem and I did this:
View.
`var model = #Html.Raw(Json.Encode(Model.myModel));
myFunction(model);`
External js.
`function myFunction(model){
//do stuff
}`

Categories

Resources