Why is this controller variable not getting through to this javascript code? - javascript

I am trying now to use my javascript to render a new view on click of an element, with this code;
$(document).ready(function() {
$('.link-panel').click( function() {
window.location.replace('/quotes/'+gon.gon_quote_id);
});
});
and i get the following error:
Couldn't find Quote with 'id'=undefined [WHERE "quotes"."user_id" = $1]
quote_controller.rb:
def show
#quote = current_user.quotes.find(params[:id])
gon.gon_quote_id = #quote.id
end
def index
#quotes = current_user.quotes.all
# how to pass the individual quote object's id to gon here
end
I think that it must be the way that I've given the url argument to the replace method, can you help me with what it is that I'm doing wrong?
(gon setup is working fine as alert tests demonstrate.)
Thanks

The script does not know that it's meant to access a variable from rails, you have to do it like so:
$(document).ready(function() {
$('.link-panel').click( function() {
window.location.replace('/quotes/'+<%= gon.gon_quote_id %>);
});
});

You should use the id parameter in the URL:
window.location.replace('/quotes/?id=' + gon.gon_quote_id);

Related

How to transfer a serialized JSON string from C# code behind to use in Javascript

The ultimate goal here is to populate fields of a Bootstrap modal from an object in the C# code behind that has all the data I need. I serialized the object from the code behind, like this:
JavaScriptSerializer serializer = new JavaScriptSerializer();
sJSON = serializer.Serialize(aerationsystem.AerationSystem);
Now I want to reference that JSON in my Javascript function, like this:
</form>
<script type="text/javascript">
function fillModal() {
var diameterValue = document.getElementById('diameter');
var aeration = <%# sJSON %>;
diameterValue.innerText = aeration.dBinDiameter;
}
</script>
</asp:Content>
(I included that closing form tag and the closing asp:Content tag so you all could see where it was that I put this Javascript: at the very end of the file.)
However, when I call that Javascript function, this is what I see in the browser's debugger:
<script type="text/javascript">
function fillModal() {
var diameterValue = document.getElementById('diameter');
var aeration = ;
diameterValue.innerText = aeration.dBinDiameter;
}
</script>
I got the idea from here: Any way to pass an object from c# code behind to javascript?
But, the means of accessing that JSON variable does not work for me. I've tried moving my script, but when I do that, I get an error that says "The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).". And I've tried other delimiters, like <%= %>, but I get the same errors depending on script placement. What am I doing wrong? How can I get that JSON string to show up in my Javascript function?
<%# %> syntax is for binding data from data source.
The easiest way is to use a Literal Server Control. It seems a bit weird inside script tag, but it does the job.
<script type="text/javascript">
function fillModal() {
var diameterValue = document.getElementById('diameter');
var aeration = <asp:Literal id="JsonLiteral" runat="server"/>;
diameterValue.innerText = aeration.dBinDiameter;
}
</script>
Code Behind
JavaScriptSerializer serializer = new JavaScriptSerializer();
JsonLiteral.Text = serializer.Serialize(aerationsystem.AerationSystem);
<%# %> is a binding block so you need call the Page.DataBind() method, whether in the Page_Load or the Page_PreRender event.
You also need to curate the string so the JSON text doesn't break your javascript:
var aeration = '<%# sJSON.Replace("'", "\'").Replace("\n", " ") %>';
thank you so much for taking the time to answer my question! I ended up solving the problem, with some inspiration from you all. Instead of using a Literal control, I ended up using a <asp:HiddenField> control on the page to store the value. Then, I pulled that its value into the Javascript variable.
The hidden field: <asp:HiddenField ID="JsonLiteral" runat="server" />
The code in the event that assigned the value:
JavaScriptSerializer serializer = new JavaScriptSerializer();
JsonLiteral.Value = serializer.Serialize(aerationsystem.AerationSystem);
And the JavaScript that finished the job:
function fillModal()
{
$(document).ready(function () {
var diameter = document.getElementById('diameter');
var control = document.getElementById('<%= JsonLiteral.ClientID%>');
var aeration = JSON.parse(control.value);
diameter.innerText = aeration.dBinDiameter;
});
}
(There's gonna be a lot more to it than just that one property, of course.)
Again, thank you all for you help, because I could not have done it without you!

Passing a currying function from Rails to JavaScript

I need to pass an URL to a .js file. This URL is generated by Rails and accepts one argument.
#routes
get "my_super/:some_id" => "controller1#my_super",
#index.html.haml
:javascript
var myUrlFunc = "#{my_super_url}"; //my_super_url(...) expects one argument
And a .js file:
$.ajax({
url: myUrlFunc($("#active_user_id"));
})
//................
The point is I don't know some_id initially as it's dynamically chosen, it's chosen from a drop down list. So I have to a function myUrlFunc which takes one argument and returns the URL instead of the URL itself. I thought this would work that it didn't due to an error:
No route matches {:action=>"my_super", :controller=>"controller1"} missing required keys: [:some_id]
What do I do about this?
As you have found out, the routing helper won't let you call it with missing parameters. Further more ruby doesn't know how to serialize a ruby method into a javascript function.
One simple, if not particularly elegant would be to pass a dummy value to my_super_url. Your function would then be along the lines of
var myUrlFunc = function(id){
var base = #{my_super_url("--DUMMY--")};
return base.replace("--DUMMY--", id);
}

Replacing an Associative Array Variable

Here is the following problem.
My javascript file contains the following code...
$(function() {
var names;
var names_hash = { };
// When an user types in a letter in the student name input field
$(".container").on("keyup", "#term", function(){
// Here we are submitting the form via AJAX. The form contains necessary
// Rails code to initiate the AJAX
$(this).parents(".student-search-form").submit();
});
$(".container").on("click", ".add_nested_fields", function() {
var term = $("#term").val();
console.log(names_hash);
});
});
Now when I enter a character into the input field with the id term the Rails controller action is called and responds with the following javascript.
FYI, #group_users_hash is just a Ruby hash and I have to call html_safe so it can be properly converted into a Javascript associative array(yes, I know it's really just an object).
names_hash = <%= #group_users_hash.html_safe %>;
console.log(names_hash);
So when AJAX finishes, I see that console.log(names_hash); has produced on my console
Object {1: "Jason"}
But when I click on the .add_nested_fields calling the on event, my console log displays
Object {}
I don't know why assoc_array isn't being updated. What's wrong with my code and how do I fix it?
It looks like your names_hash (which you redefine in your return anyways via var names_hash and then shadow any higher scoped variables) is not in the same scope as the the one in which you are priting it on click. Thanks to your wrapper function. You're going to need some way - via events or callbacks, etcetera - to access the variable within that scope and set it to the value you wish to use.
EDIT
A non-ideal but sample solution to further explain woudl be:
var names_hash = {};
$(function() {
$(".container").on("click", ".add_nested_fields", function() {
console.log(names_hash);
});
});
And then when your response comes in you simply:
names_hash = <%= #group_users_hash.html_safe %>;
And then you should be golden. The reason this is not an ideal is because you have your names_hash floating in global scope. It's best to "namespace" such as:
(function() {
// prevent redefining it if it's already defined via another file
var MyNamespace = window.MyNamespace || {};
MyNamespace.names_hash = {};
window.MyNamespace = MyNamespace;
})();
$(function() {
$(".container").on("click", ".add_nested_fields", function() {
console.log(MyNamespace.names_hash);
});
});
And from there you modify your response to:
MyNamespace.names_hash = <%= #group_users_hash.html_safe %>;
And viola. You've protected global scope and you've also publicized the functions you want to access outside of the wrapper function.

__dopostback is not working in javascript function

am calling __dopostback function in javascript while closing event of browser but its not working in Chrome.
the same function is working in IE
can any one give me the solution.
<script type="text/javascript" language="javascript">
function doUnload()
{
var btnlogout = document.getElementById("ctl00_lbtn_Logout"); alert(btnlogout);
__doPostBack(btnlogout, '');
}
</script>
When doing a __doPostBack, you need to pass the control's UniqueID via javascript. ClientID will not work.
I think you should be passing the btnlogout id as string (not sure if you have to remove the ctl00 thing since it's a child control) as the function expects text and it is probably resolved during the request on the server..
Take a look at this article:
http://wiki.asp.net/page.aspx/1082/dopostback-function/
Just do:
btnlogout.click();
since you already have a reference to the button and, by the way, don't get the element the way you are doing it; do this instead:
var btnlogout = document.getElementById("<%=btn_Logout.ClientID%>");
dopostback(clientID, args)'s first parameter must be a control's clientid, it is a string , not object (of course string is object ) ..
in your case , i assume that is 'ctl00_lbtn_Logout', pass the right params like :
__doPostBack('<%= downloadUp.ClientID %>', current_index);
if your control is server side control, change 'downloadUp' to your control's id , else you just need pass the id
Please try to getElementById this way
var btnlogout = document.getElementById('<%= lbtn_Logout.ClientID %>');
alert(btnlogout)
and test it again , it will work..

Passing event args from javascript to code-behind while using ClientScript.GetPostBackEventReference

I'm trying to trigger a postback from java-script and also pass event args. I'm able to trigger the postback **but not able to pass event args.
The below function does not work. It does not like the args parameter in ClientScript.GetPostBackEventReference.
<script type="text/javascript">
function TriggerServerSideClick(args) {
//btnDummy is a asp.net server-side button control
<%=ClientScript.GetPostBackEventReference(btnDummy, args , true)%>
//tried this -> <%= 'ClientScript.GetPostBackEventReference
// (btnDummy,' + args + ', true)' %> ,
// but i guess i am definitely missing something.
}
</script>
What am I missing here ?
I know that the following works
__doPostBack('btnDummy', args);
but want to stay away from __doPostBack as that could change eventually and try the ClientScript.GetPostBackEventReference instead.
Thanks for your time.
#Brian: Thanks a lot for following up. I tried your placeholder approach but I am getting a javascript error. (Message: Expected ';')
Here is the viewsource snippet:
var postbackUrl = '__doPostBack('ctl00$MainContent$btnDummy','{0}')';
function TriggerServerSideClick(args) {
var url = String.format(postbackUrl, args);
eval(url);
}
Try this:
var postbackUrl = '<%=ClientScript.GetPostBackEventReference(btnDummy, "{0}", true)%>';
function TriggerServerSideClick(args) {
var url = String.format(postbackUrl, args);
eval(url);
}
Put a placeholder where the argument should be, then use a client-side method to replace the placeholder (client-side String.format method) and use that to postback.
HTH.
The answer from Brian Mains sent me in the right direction when I was working on this issue just now. The only difference being, that I didn't use the client-side string.Format - I used the mainstream JavaScript string.replace:
//js
args = someComplicatedDynamicStuff();
myPostback = <%= Page.ClientScript.GetPostBackEventReference(this, "args")
.Replace("'", "\\'") %>; // server-side replace to
// inject string delimiters
eval(myPostback.replace('args',args));

Categories