Need to render variable from route to use in client-side javascript - javascript

I am currently able to use variables in the view that I render from the route but only in the HTML markup. How can I use these same variables in the client-side javascript?
I have this code:
<script>
var socket = io();
if ({{highestBidder}} === {{sessionID}}) {
socket.on('outbid', function () {
console.log('You have been outbid');
});
}
</script>
However, the variables are not being passed in correctly because I'm just getting an undefined.

As far as I know you can't ! Since most of the data is compiled in the server and rendered as HTML page. But there is work around for this :
Create AJAX call. Get whatever data you like with it.
Store the variables as hidden field and grab then using JS or jQuery [I don't suggest doing this.]

Related

pass data from javascript to asp.net core 2 razor page method

Is there any to pass some data from HTML property on changed event data to asp.net core razor pages?
I want to get an ID from dropdown list from HTML using JS and pass it to Razor Pages (asp.net core 2) and get the result from the custom method ?
Code I want to be look like below if possible :)
JS code
$('#Neighborhood_DistrictId').on('change', function () {
#Model.GetDistrictName($('#Neighborhood_DistrictId').val());
});
On the Razor page
public string GetDistrictName(Guid id)
{
return httpSystemApi.GetByIdAsync<District>("Districts", id).Result.Name;
}
GetDistrictName method is connecting to API and returning the value. I don't want to direct connect to API with JS if there is a way to do what I want
I am playing around with Razor Pages, and I have the same issue. Below is my work around. It seems like there should be some event handler will do the same thing, but I have not found another way yet. I tried treating it like the MVC controller, but I believe there is some form token that it is expecting so that did not work [name="__RequestVerificationToken"].
Basically what I am doing here, is tricking the page into thinking I clicked a button and then telling it which function to look at. Additionally, you have access to all your model fields so you do not need to pass them.
Here is the select list:
<div class="col-md-2"><select id="ddlPortalName" asp-for="selectedPortalName" asp-items="Model.portalNames" onchange="ConcatenateURL();"></select></div>
And then here is the JS function, notice I had to change the form action to tell it which page function to look at.
<script type="text/javascript">
function ConcatenateURL() {
document.forms[0].action = "VisibilityTest?handler=ConcatURL";
document.forms[0].submit();
}
</script>
And then finally here is the c# file method.
public void OnPostConcatURL()
$('#Neighborhood_DistrictId').on('change', function () {
#Model.GetDistrictName($('#Neighborhood_DistrictId').val());
});
#Model.GetDistrictName is a server side method not Usage directly inside script
$('#Neighborhood_DistrictId').on('change', function () {
var url="http://localhost/{controllername}/{methodname}/id=";
url=url+$('#Neighborhood_DistrictId').val()
$.get(url,function(data){
...some code
});
});
var url="http://localhost/{controllername}/{methodname}/id=";
In mvc 5 genrate url from server side and set the client side variable
var url='Url.Action("{action}","{controllername}","actionname")';
this is only way for call the controller using javascript or jquery not Directly use server side method in javascript.

What's the correct way to send Javascript code along with rendered HTTP to a client?

Mid development I decided to switch to server-side rendering for a better control amongst other benefits. My web application is completely AJAX based, no url redirecting, so the idea here is a website that builds itself up
I just couldn't figure out the proper way to send javascript events/functions along with the html string, or should all the necessary javascript always be preloaded in the static files?
Let's say client clicks a pre-rendered button 'open table'
The server will make a query, build the html table and send it back, but this table also needs javascript triggers and functions to work properly, how are these sent, received and executed?
There are a couple of articles that mention to not use eval() in Javascript, is there any way around this? I don't want to have to preload unnecessary events for elements that don't yet exist
The server is Python and the Client is Javascript/JQuery
Theoretical example :
Client Base Javascript :
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
$("#table_div").append(response.html);
eval(response.javascript()); //??
}
});
Python Server(views.py) :
def get_table(request):
data = {}
#String containing rendered html
data['html'] = get_render_table()
#String containing Javascript code?
data['javascript'] = TABLE_EVENTS_JAVASCRIPT
return HttpResponse(json.dumps(data),content_type='json')
Worth noting my question comes from an experimental/learning perspective
Update:
You can use jQuery.getScript() to lazy load JS. I think this solution is as close as you can get to run JS without using eval().
See this example:
jQuery.getScript("/path/to/script.js", function(data, textStatus, jqxhr) {
/* Code has been loaded and executed. */
console.log( data ); // Data returned
console.log( textStatus ); // Success
console.log( jqxhr.status ); // 200
console.log( "Load was performed." );
});
and "/path/to/script.js" could be a string returned from $.getJOSN response.
Also, the documentation for getScrippt() has examples on how to handle errors and cache files.
Old Answer:
Using .on() attaches events to current and future DOM elements.
You can either attache events prior to DOM insertion or attache event after DOM insertion.
So in your example you can do something like:
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
var code = $(response.html);
code.find(".elementToFind").on("click", function (){
// Code to be executed on click event
});
$("#table_div").append(code);
}
});
I did not test the code but I think it should work.
Assuming you can't just set up an event-binding function and then call it from the main script (the JavaScript you need can't be guessed ahead of time, for example) then one really easy way is just to append the JavaScript to the bottom of the returned HTML content within script tags. When it's appended along with the HTML, the script should simply execute, with no eval() required.
I can't swear that this would work in old browsers, but it's a trick I've used a couple of times, and I've had no problems with it in Firefox, Chrome, or any of the later IE versions.
I think I see what you're asking here, from my understanding you want to send the new "page" asynchorously, and render the new javascript and html. It looks like you already got your request/response down, so i'm not gonna go and talk about sending JSON objects, and the whole "how-to" of sending html and javascript because it looks like you got that part. To do what you want and to dynamically add your javascript in, this stackoverflow question looks like it has what you need
Is there a way to create a function from a string with javascript?
So pertaining to your example, here is how it would look when you recieve the JSON string from your python script:
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
$("#table_div").append(response.html);
/* Create function from string */
var newFunction = Function(response.javascript['param_1'], response.javascript['param_2'], response.javascript['function']);
/* Execute our new function to test it */
newFunction();
}
});
*Your actual function contents would be the string: response.javascript['function']
*Your parameter names if any would be in separate strings ex: response.javascript['param_1']
That is almost a direct copy of the "String to function" code that you can see in the linked question, just replaced it with your relevant code. This code is also assuming that your object is sent with the response.javascript object containing an array with your actual function content and parameter names. I'm sure you could change the actual name of the var too, or maybe put it in an associative array or something that you can keep track of and rename. All just suggestions, but hopefully this works for you, and helps you with your problem.
I am also doing similar work in my project where I had to load partial html using ajax calls and then this partial HTML has elements which requires events to be attached. So my solution is to create a common method to make ajax calls and keep a js method name to be executed post ajax call in html response itself. For example my server returns below html
<input type="hidden" data-act="onPartialLoad" value="createTableEvents" />
<div>.........rest of html response.....<div>
Now in common method, look for input[type='hidden'][data-act='onPartialLoad'] and for each run the method name provided in value attribute (value="createTableEvents")
Dont Use Eval() method as it is not recommended due to security
issues. Check here.
you can run js method using window["method name"]...so here is a part of code that I use.
$.ajax(options).done(function (data) {
var $target = $("#table_div");
$target.fadeOut(function () {
$target.html(data);
$target.fadeIn(function () {
try {
$('input[data-act="onPartialLoad"]', $target).each(function () {
try {
//you can pass parameters in json format from server to be passed into your js method
var params = $(this).attr('params');
if (params == undefined) {
window[$(this).val()]();
}
else {
window[$(this).val()]($.parseJSON(htmlutil.htmlDecode(params)));
}
} catch (e) {
if (console && console.log) {
console.log(e.stack);
console.log($(this).val());
}
}
});
}
catch (e) {
console.log(e.stack);
}
});
});
});
use jQuery.getScript() (as suggested by Kalimah Apps) to load the required js files first.

In my asp.net-mvc file, how can I move my javascript to a seperate js file?

I have a bunch of javascript inside my view and its getting quite large so I want to move it to a separate js file. The one issue I have is that I have this line:
var tags = <%= new JavaScriptSerializer().Serialize(Model.Tags) %>;
which I obviously can't just copy over since it has the server side asp.net-mvc tags. What is the recommended way to deal with that:
Keep this one function inside the aspx page and have the javascript from the seperate js file call that function?
Other??
What you could do is have a JavaScript object contain all the information you get from the controller and pass it through a javascript function which is located in the external javascript file. You can also pass other information through the options variable.
Example:
var options = {
tags: <%= new JavaScriptSerializer().Serialize(Model.Tags) %>
};
initPage(options);
Usage:
function initPage(options) {
console.log(options.tags);
}
This depends a lot on the way you want to use it and the level of repeating.
Some thoughts:
The tags are static. Then I guess then don't really need to be in the model. So you can move them into a new Controller action which outputs the scipt. You can call this action in the <script> part of your view.
The tags are changing very frequently (maybe even at every page load). Then there is no gain in moving this in a separate script file.
If you set up your javascript file with proper closures, you can expose a property (or better yet, a parameter to the object/method) with which to pass that information along when you call that function.
Your Javascript would need to be something like this:
var JsFile = (function() {
var tags;
// list all of your methods here.
return {
var setTags = function(_tags) {
tags = _tags;
}
};
})();

send data to JS file without using global variables

I need to send data in a HTML page to a script file that is loaded in that page. The simplest way i can think of is to use a global variable which is defined in the page and accessed in the script file.
We all know global state is bad, so i started thinking about the options available for passing data from HTML page to script file without using global state. I cant find (or think of) any.
I am curious whether this is possible. Any ideas?
It really depends what you're doing. In general, I wouldn't advise this methodology, but it's something to consider depending on your circumstances. For the sake of this example, I'll assume you're using jQuery (if not, replace the document.ready with whatever you want to use for onDOMReadyStateChange monitoring).
In the HTML:
<script type='text/json-data' id='some_data_set'>
{ 'foo': 'bar', 'baz': 1 }
</script>
In the JavaScript:
$(function() {
var myData = JSON.parse($('script#some_data_set').html());
// YOUR CODE GOES HERE
});
Nope. All the javascript scope starts from a global level, therefore you must have at least one global reference to your data.
Let's say you wanted to store a list of products and events:
var myGlobalData = { "products":<products>, "events":<events> };
Where <products> and <events> are two different data blocks.
If you're paranoid on global objects, you can simply delete the reference point (thus it's contents) after you finished using it, as follows:
delete window.myGlobalData;
One option is to scope your data. For example, in JS file you can define an object like:
var processor = {
function setData(o) { // do stuff
}
};
Then in your HTML you know that the data is scoped to the processor. So you can do something like:
processor.setData({someData});

AJAX & ASP.net, Referencing server controls in external file

I've got some JavaScript in an ASP.NET page that looks like this:
var list = $get('<%=Topics.ClientID %>');
I have many functions written now where this syntax is used, and I would like to centralize my JavaScript and move this into an external JavaScript file. This breaks however, since 'Topics' cannot be found.
What is the best strategy for getting this to work? I assume I should pass the control/control information as a parameter to the function, but I can't seem to get the syntax to work. Any suggestions?
It's a common problem for ASP.NET JS development. As for me, I'm using same approach each time and it looks fine.
I'm used to OOP in Javascript, so most my JS external files look like:
function CouponManager()
{
}
And in .aspx code i do:
<script language="javascript">
var couponManager = new CouponManager();
</script>
If I need to pass some parameters I change the declaration of class to:
function CouponManager(params)
{
// .. stuff here
this.initialize = function(initParams)
{
// .. accessing initParams variable for server control IDs
};
this.initialize(params);
}
And from .aspx code I do the following:
<script language="javascript">
var couponManager = new CouponManager
({
txtCouponNameId = '<%= txtCouponName.ClientID %>',
txtCouponDescriptionId = '<%= txtCouponDescription.ClientID %>'
});
</script>
This approach allows me to separate JS from .aspx page and have all server control dependencies in a single tag.
You should create a javascript method from inside the usercontol which returns the client side element. Then in your other page/control, just access that method
In User Control
<script language="javascript">
function GetTopics() {
return = $get('<%=Topics.ClientID %>');
}
</script>
In other page/control
<script language="javascript">
var list = GetTopics();
</script>
Edit - The problem you are facing is you need Topics.ClientID where it doesn't exist. So the only real way to bridge that gap is to put it in a common place. If you really don't want to do that, you can try and select your element by some other criteria. If you are using jQuery, you could mark an element with a class of Topics then find it with $(".Topics").
if you know that you only have one server control called "Topics" per page, and you use naming conventions you can inherit from whatever the control Topics is (maybe it's a HiddenField? you don't specify) and override its ClientId getter to return its server id like this:
http://andreascode.wordpress.com/2009/04/27/tiny-drips-of-aspnet-juice/
then you can know in your javascript files that there will be a hidden field in the page with the id set to "Topics" and use that directly.
depending on your domain/situation this could either save you a lot of time or screw you over big time.

Categories