Best way to get server values into JavaScript in .NET MVC? - javascript

Using ASP.NET MVC + jQuery:
I need to use some values owned by the server in my client-side JavaScript.
Right now, I've temporarily got a script tag in the actual view like this:
<script>
var savePath = '<%= Url.Action("Save") %>';
</script>
But I want to move it into something cleaner and more maintainable. I'm thinking of something along the lines of creating a JavaScript controller/action and returning a JSON object that would contain all the data I need, then using the view as the src for a script tag.
Any other ideas?

This actually depends. For simple inliners, the line above works just fine. If you need a LOT of server data in the JavaScript, your view approach may work. However you'll get the same result if you just render partial view that outputs the required JavaScript.
There's a problem with this, since you may end up mixing server data with JavaScript. The best approach would be to minimize server data to absolute minimum, and pass it to JavaScript functions instead of mixing with JavaScript code. That is, not
function func() {
var path = '<%= Url.Action("my") %>';
$(".selector").append("<img src='" + path + "' />");
}
but
function AppendImageToSelector(path) {
$(".selector").append("<img src='" + path + "' />");
}
function func() {
var path = '<%= Url.Action("my") %>';
AppendImageToSelector(path);
}
This makes the code cleaner and easier to understand, helps to move JavaScript out to separate .js files, helps to re-use JavaScript when needed, and so on.
If you need a lot of server-related URLs in JavaScript, you may want to create global (in master page) function like
function url(relative) {
return '<%= Url.Content("~") %>' + relative;
}
and use it from JavaScript scripts. This technique is questionable, though; for example it doesn't use MVC routing rules so URLs may not be out of sync; etc.

I know this is not applicable in all cases but when I need to pass an Url to a client script (as in your example) it is often to ajaxify some anchor or button I already have in the DOM:
<%= Html.ActionLink("Save data", "save") %>
and in my script:
$('a').click(function() {
$.get(this.href);
return false;
});

Stephen Walther - ASP.NET MVC Tip #45 – Use Client View Data

Related

How to write ruby method in js file

I'm trying to display in each cell of my calendar in js (fullcalendar) a ruby method “week_balance” where I have some informations but I can't.
I write :
dayRender:function(cell, week_balance){
$(cell).html(‘<span>’ + week_balance + ‘</span>’);
},
It doesn't work, why ?
Thanks.
If you are using Rails framework, then it provides an option where you write ruby code in Js file.
For this, you need to change extension for js file to .js.erb
And then call ruby function is js method as,
dayRender:function(cell, week_balance){
$(cell).html('<span>' + "<%= week_balance %>" + ‘</span>’);
},
make sure week_balance is accessible without any parent. Else make it class method and use it.

Embedding MVC Model variables int Javascript code

I have some Javascript code shown below. It uses a replacement variables from the model which are working fine - however I cannot work out how to get the content location from the model. I have
function drawChart() {
$.post('#Url.Content("~/Home/GetDataAssets")', function (d) {
var data = google.visualization.arrayToDataTable(d);
var options = {
title: '#Model.Title',
width: '#Model.Width',
height: '#Model.Title',
allowHtml: #Model.AllowHtml,
is3D: #Model.Is3D
};
But I want the #Url.Content line to look something like
$.post('#Url.Content("#Model.ContentLocation")', function (d) {
Which doesn't work as it thinks that #Model.ContentLocation is a string. When I try escaping the quotes I do not get the required result as they are being Html encoded. I believe that is because I am doing it incorrectly.
What is the correct way to encode the quotes so that the data will be read from the location in the model variable?
With the help of Stephen Muecke I have got this working. The line making the post should have been:
$.post('#Url.Content(Model.ContentLocation )', function (d)
JavaScript does not understand MVC "~/..." path syntax. If your intention is to use that in Ajax post or get you need to get the actual path of that virtual path. To do that, you can do this from the server side code when you setup the model:
var urlHelper = new UrlHelper(Request.RequestContext);
var model = new ModelClassNameHere {
ContentLocation = urlHelper.Content("~/blah/nicepic.jpg") };
return View(model);
One other thing that I'd suggest is to cache all these server side model properties into a global page setting in JavaScript as to centralized things and not having #Model.blah everywhere. Beside if you are going to split your javascript files into multiple files during development, this is just good practice.
See this example: https://dotnetfiddle.net/ZlOL0n
I am using angular.module.value to cache that global pageSettings that contains server side model contents so I can pass them around in angular. See how the settings value are injected into the controller.

Add modal window in ejs file

I wrote a little program with node js and I used ejs as a template. In my program, I calculate two parameters 'msg1' and 'msg2' that I want to show on a modal window. Unfortunately I couldn't do that with ejs.
As I understand it, you're running the .ejs template on the server, not the client.
Anything inside <% %> runs as part of the template, which means it's trying to call alert in the server. This should fail.
You haven't said what msg1 and msg2 are. If they're client-side variables then all you need is:
function alertNumber() {
alert(msg1 + msg2)
}
which would mean you don't even need templating - it's just an HTML file. On the other hand, if msg1 and msg2 are server-side variables, they need to be inserted using the template. A naive way of doing so would be like this:
function alertNumber() {
alert('<%- msg1 + msg2 %>')
}
This only works if msg1 + msg2 doesn't contain the characters ', \, newline, carriage return, and possibly others I've missed. If it does, the script will probably fail. In particular, don't do this unless msg1 and msg2 are from a trusted source, because whoever controls them will be able to inject any javascript code they want into the client. However, if you can guarantee that they're numbers then this won't be a problem.
Last but not least... you've defined alertNumber. Have you actually used this function?

"The name does not exist in the current context javascript" + Window.Location

Using javasciprt function for performing the similar function as Response.Redirect.
function redirectToHome(sessionID) {
window.location = '<%= ResolveUrl("~/default.aspx") + "?SessionGUID="+ sessionID %>'}
Passing sessionID from codebehind:
string sessionId = system.guid.new().tostring();
btnClose.attributes.add("OnClick","javascript:function(redirectToHome("sessionId" ));");
Code maybe not exactly the same but i am doing pretty much above.
But at the page rendering its giving error message
"the sessionID does not exist in the current context javascript"
Please suggest another way of doing this.
In your redirectToHome function
window.location = '<%= ResolveUrl("~/default.aspx") + "?SessionGUID="+ sessionID %>'
The entire string is within <% ... %>, hence rendered by .NET before being passed down to the server. So sessionID there will be assumed to be a .NET variable, and whatever you pass to the javascript function will never be used. (Try "view source" so see what your code really renders like)
You need to either move sessionID outside of the .NET block:
window.location = '<%= ResolveUrl("~/default.aspx") %>' + '?SessionGUID=' + sessionID;
or generate the session id from the .NET block immediately when creating the function:
window.location = '<%= ResolveUrl("~/default.aspx") + "?SessionGUID="+ System.Guid.NewGuid().ToString() %>'
If you do decide to pass the session ID through the javascript variable, you have to make note of some additional issues:
Your code will currently print something like (assuming you've fixed the string concatenation issue):
onclick="javascript:function(redirectToHome(e4bd5302-a77c-40f4-9439-6b510bb4cdf3))"
This has a set of problems:
You don't need to specify javascript: in onClick as it is already a javascript-specific attribute.
You shouldn't wrap that code in function( ... )
You're not quoting the string ID
The correct call would look something like this:
btnClose.attributes.add("OnClick","redirectToHome('" + sessionId + "');");
Note that this could equally well be written as:
btnClose.OnClientClick = string.Format("redirectToHome('{0}');", sessionId);
which is perhaps more readable.

How to pass a javascript variable into a erb code in a js view?

I have this Javascript view in my Rails 3 project:
app/views/expenses/new_daily.js.erb
var i = parseInt($('#daily').attr('data-num')) + 1;
//$('#daily').append('agrego fila ' + i + ' <br />');
$('#daily').append('<%= escape_javascript(render(partial: 'new_expense', locals: { i: i })) %>');
$('#daily').attr('data-num', i);
I want to pass my 'i' javascript variable to a ruby partial through locals, How I can accomplish this?
As far as i know there is no way to do it directly and the reason is fairly simple too, html is executed at the server side and javascript is a client side language which means its executed in your local browser, thats why if you even try to pass a variable between the two you'll have to make a request to the server,
However this problem is tackled by calling an AJAX request, this AJAX request does the same thing as sending a new request to the server however it does that without refreshing or reloading the page to it gives the users the illusion that no request was made.
a guy asks a similar question Here
and you can learn more about AJAX Here on MDN:
Yes you can pass the value by using jquery;
<%=f.text_field :email ,:id=>"email_field" %>
<script type="text/javascript">
var my_email= "my#email.com"
$(document).ready(function(){
$("#email_field").val(my_email);
});
</script>
Simple answer is you can't. Partials are expanded at server side, and JavaScript variables are set later at client side. You could make i (as a variable name) a parameter of the partial and use it there.
render :partial => 'xx', :locals => { :variable => 'i' }
And in partial
alert(<%= variable %>);
Check out the gon gem. https://github.com/gazay/gon
It gives you a simple object you can pass variables to that will be available to your scripts via window.gon
Also referenced here
http://railscasts.com/episodes/324-passing-data-to-javascript
1) You may create a js tag with global variable in you erb template, after that you will be able to access that variable from any js file
<%= javascript_tag do %>
window.productsURL = '<%= j products_url %>';
<% end %>
2) You can pass data to data-attribute in erb template and access it by js on client side that way $('#products').data('products')
<%= content_tag "div", id: "products", data: {products: Product.limit(10)} do %>
Loading products...
<% end %>
3) You can use gon, to use your Rails variables in your js
There is a good article, read it and fine solution for your specific case
http://railscasts.com/episodes/324-passing-data-to-javascript,
more comments are here http://railscasts.com/episodes/324-passing-data-to-javascript?view=asciicast
Here's a few different options on how to do it:
http://jing.io/t/pass-javascript-variables-to-rails-controller.html
The best other answers here are right that this can't be done by passing the javascript variable into an erb partial, since it is rendered on the server, not the client.
But since anyone looking for this is probably interested in a work-around solution, which I don't see here, I will post this example that works well with Rails UJS and Turbolinks.
First, you set up your controller to return a partial as HTML:
format.html { render partial: "new_expense" }
Next, write a javascript AJAX function in app/views/expenses/new_daily.js.erb:
var i = parseInt($('#daily').attr('data-num')) + 1;
$.ajax({
url: '/daily',
type: 'GET',
dataType: 'html',
contentType: "application/html",
success: function(response) {
$('#daily').replaceWith(response)
$('#daily').attr('data-num', i);
}
});
This is going to get your Rails partial as an html fragment that you can use to replace that part of your rendered page. You can use jQuery to get your data-num attribute value, do some math on it, replace the partial in your view, and then set the attribute value again.
You may ask why go to all the trouble of getting the Rails partial and replace it on the page, instead of just getting the data attribute, doing math on it, and setting that? The answer is that this is the best, and perhaps the only way of doing something which is really essential when rendering a Rails partial using UJS while handling an asynchronous response to an action.
If you are handling an asynchronous response from your server in a create.js.erb template, then your variables (#daily, for example) are not going to reflect the work done after the request has completed (for example, if there has been processing on a background server like Sidekiq). In that case you don't have up-to-date action response variables to pass into your Rails partial in the js.erb file, but you also can't pass the javascript data response into your partial, as pointed out in this question.
As far as I know, this approach is the only way to get a fully up-to-date partial after receiving a response to an asynchronous response (not shown). This get you the up-to-date partial, allows you to get your javascript into it, and is flexible enough to work in pretty much any use case.
Let's make shure we understand each other. Your erb template (new_daily.js.erb) will be processed on the server side, ruby code will be evaluated (within <% %>), substitution made, and then resulting javascript will be sent to browser. On the client side the browser will then evaluate this javascript code and variable i will be assigned a value.
Now when do you want to pass this variable and to what partial?

Categories