Async Problems with jQuery & Javascript - javascript

I'm going round in circles and can't seem to figure out a solution from the resources currently available here on Stack or Google. There's got to be something obvious that I'm missing, perhaps you might be able to help?
Story summary:
A javascript function launches when clicked and creates a new contact in our database.
Additional functions are then called upon successful creation to toggle some settings where necessary, dependant on a few checkboxes.
Calls are currently being made asynchronously, resulting in only the last function call to successfully update the contact.
I can't, for the life of me, get the call to work one after the other instead.
Each call returns a JsonResult upon successful completion, if that helps at all (needed for other areas of the application.
Code currently looks like:
function CreateClicked(){
Contact.Create(**bunch of params**, function(data){
if(data.success) {
togglePrimary(data.newId);
toggleBilling(data.newId);
toggleTechnical(data.newId);
toggleBalance(data.newId);
toggleSecurity(data.newId);
toggleMarketing(data.newId);
Modal.Load(**loads a modal view**);
}
}
}
The toggle functions then look like:
function togglePrimary(id) {
if ($("#contact_admin_primaryrole").prop('checked'))
{Contact.TogglePrimaryRole(id);}
}
Which calls a controller function that looks like this:
public JsonResult TogglePrimaryRole(int contactId){
try{
var c = new Contact(contactId);
c.IsPrimaryContact = !c.IsPrimaryContact;
c.Update(AuthenticatedUser.Username, !c.IsPrimaryContact);
return Json(JSONResponseFactory.SuccessResponse("Contact updated successfully"));
}
catch (Exception ex){
return Json(JSONResponseFactory.ErrorResponse(ex.Message));
}
}
How should I go about setting this up so that each toggle function doesn't start until the previous one has finished and returned a Json response, regardless of success?
Any ideas?
Cheers,
Dez

Using jQuery promises should help:
togglePrimary(data.newId).then(toggleBilling(data.newId)).then(toggleTechnical(data.newId)
etc.
This will run the next function only if the last one was a success. If you want to call the function irrelevent of the outcome then use always() instead of then()
togglePrimary(data.newId).always(toggleBilling(data.newId)).always(toggleTechnical(data.newId)
This will require jquery 1.6 or higher to be referenced. To reference from the CDN add the following
<script src="http://code.jquery.com/jquery-1.9.0.js"></script>

I couldn't seem to get anywhere with promises, or javascript function chaining with callbacks... so I turned the values of each status into an array of strings and parsed it within the controller instead!
Thanks for helping :)

Related

I am looking to call a JS Function inside a Razor function

I am looking to call a JS function inside of a Razor function but I am unable to find the right syntax for it. I am not sure if I need to reorder my placement but I do not think it is necessary.
I have tried calling it as a new object and passing that into to the .Action() function but I could not get that to work. I am not super familiar with JS and if you could explain your answer that would be very appreciated!
#Html.Action("MonthlyPSAGauge", "Display", DropDownValue())
function DropDownValue() {
var value = $("#productionLine-dropdown").data("kendoDropDownList").value();
return { selectProductionLine: value };
}
I want to pass the DropDownValue() value into the MonthlyPSAGauge method in the Display Controller.
Unfortunately that will not work, C# is server side and JS (in this case) is client side. To make C# "call" a js function you could use something similar to this.
#Html.Raw(<script>DropDownValue();</style>);
Which would paste this into the html and would be run on the clients machine, I hope this helps!

Call a Javascript form within a controller in MVC4

I want to call a javascript function from within a controller function that I use:
Public Function redirectTo() As JavaScriptResult
Return JavaScript("ToSignUp()")
End Function
in my controller. But the program never goes to the script. I've already checked similar answers but I haven't found any solution to the problem. Can someone assist me with this?
ADDITION 4/3/19 12:41
I use the following for redirection from my controller... but nothing is happening:
Public Function redirectTo() As RedirectToRouteResult
Dim routes As New RouteCollection With {.RouteExistingFiles = True}
Return RedirectToAction("../login/SignUp")
End Function
End Class
ADDITION 4/3/19 23:20
The issue was solved by this way
In the code behind of my .aspx Page and at the proper place I add it the following code:
Dim routes As New RouteCollection With {.RouteExistingFiles = True}
Response.Redirect("SignUp")
The Response.Redirect instruction is not new.
But in order to be functional it needs to add before the following instruction
Dim routes As New RouteCollection With {.RouteExistingFiles = True}
And that is because the MVC did not recognize the existent files which means the property RouteExistingFiles is always False
Thus in order to work the code we need to turn this property to True
Anyway thanks to all for your assistance.
From other examples online (like this one), I would say that if you temporarily changed your function to:
Public Function redirectTo() As JavaScriptResult
Return JavaScript("alert("HERE");")
End Function
It will likely work... so without seeing the JS function contents, it's hard to tell. To the second point, a RedirectToAction call will work if called from the server; if the client is calling this, use 'window.location' instead.

Running client side javascript without loading a new (blank) view on Odoo 8

I need to run some client-side javascript from a button in a form view in Odoo 8. This button runs a python method which returns this dictionary:
{"type": "ir.actions.client",
"tag": "my_module.do_something",}
do_something is defined in a .js file as follows:
openerp.my_module = function (instance) {
instance.web.client_actions.add("my_module.do_something", "instance.my_module.Action");
instance.my_module.Action = instance.web.Widget.extend({
init: function() {
// Do a lot of nice things here
}
});
};
Now, the javascript is loaded and executed properly, but even before launching the init function, Odoo loads a brand new, blank view, and once the javascript is over I can't get browse any other menu entry. In fact, wherever I click I get this error:
Uncaught TypeError: Cannot read property 'callbackList' of undefined
What I need instead is to run the javascript from the form view where the button belongs, without loading a new view, so both getting the javascript stuff done and leaving all callbacks and the whole environment in a good state. My gut feeling is that I shouldn't override the init funcion (or maybe the whole thing is broken, I'm quite new to Odoo client-side js) , but I couldn't find docs neither a good example to call js the way I want. Any idea to get that?
Sorry, I don't work on v8 since a lot of time and I don't remember how to add that, but this might help you: https://github.com/odoo/odoo/blob/8.0/doc/howtos/web.rst
Plus, if you search into v8 code base you can find some occurence of client actions in web module docs https://github.com/odoo/odoo/search?utf8=%E2%9C%93&q=instance.web.client_actions.add
Thanks to the pointers simahawk posted in another answer, I have been able to fix my js, which is now doing exactly what I needed. For your reference, the code is as follows:
openerp.my_module = function (instance) {
instance.web.client_actions.add("my_module.do_something", "instance.my_module.action");
instance.my_module.action = function (parent, action) {
// Do a lot of nice things here
}
};

How to redirect to a play framework url from within javascript without hard-coding the url

I need to do something seemingly quite simple.
In the same way that I can, from my scala.html file, create a link to another url, /entry, I need to do that from a javascript file.
i.e., from the scala.html:
<div class="footer">
<a href='#routes.Application.index()'>Home</a>
</div>
from my javascript event:
function() myEvent {
window.location="#routes.Application.entry()"; // DOESN'T WORK!
}
For routing from javascript, I've already had to setup my javascript routes for some ajax work I've already had to do.
My ajax work was calling a method 'findPersons()' so in my Application.java file, I had already:
public Result jsRoutes()
{
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter( "appRoutes",
routes.javascript.Application.findPersons()));
}
Because I want to be able to redirect to my GET entry() method, I modified it to look like this:
public Result jsRoutes()
{
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter( "appRoutes",
routes.javascript.Application.findPersons(),
routes.javascript.Application.entry()));
}
Additionally I have these in my routes file:
GET /entry controllers.Application.entry()
POST /findPersons controllers.Application.findPersons()
When I am invoking my findPersons method, it is really nice and simple.
It looks like this:
appRoutes.controllers.Application.findPersons().ajax({
data: {
personIdentifier : personIdentifier,
surname : surname,
givenNames : givenNames
},
success : processDBQuery
});
For my simple redirect, I would like to be able to maintain the same loose coupling between my html/javascript code and the urls, as I can the ajax call above.
My redirect needs to occur on an event. Therefore, the easiest and quickest solution would have been simple to write:
function() myEvent {
window.location="/entry";
}
However, then I would be hard-coding the URL (which I have managed to avoid for my ajax call above), no longer maintaining that loose coupling I would so much like to have.
However, I see no examples in the documentation, and from what I have in the generated javascript (for my routes) there is no chance.
Is there any way to achieve what I am after?
thanks for reading!
p.s., I should add; I guess I have also thought of the possibility of using the ajax call that is generated, I guess I can probably fetch the page I want... and there is probably a means of replacing the current document with the entire content of the fetched page. but that just sounds bad.... wrong...
or not?
I was rather hoping for a substitution, as is done in my html
i.e, my link as shown above is generated to look like this:
<div class="footer">
<a href='/'>Home</a>
</div>
In the same way, I hoped there was some means of substitution in the javascript, so that the event function above ends up in being massaged into looking like this:
function() myEvent {
window.location="/entry";
}
Jacques, from the above comments, helped me to realize a work-around.
From within my "assets located" javascript file, I can still refer to page/template located javascript.
Own-file/assets located javascript doesn't seem to be transformed how I expected.
However, Page/template located javascript is transformed exactly how I require.
I can refer to a template located javascript function from my assets located javascript.
This means, I have a little work-around of one extra little function inside the template which does the redirection for me.
i.e.,
myJavascript.js:
function personResultsListClickHandler(personId) {
var fpersonId = personId;
return function() {
window.alert("hello! " + fpersonId);
affectRedirect();
};
}
myTemplate.scala.html
#main("person lookup") {
<script type="text/javascript">
function affectRedirect(){
window.location="#routes.Application.entry()";
} // Need this here so it will be transformed.
// asset located javascript doesn't seem to get transformed like javascript here in template! :(...
</script>
Another possibility is the fact that the Javascript object retrieved by calling:
appRoutes.controllers.Application.entry()
contains a url member. This url member is exactly what I can use to assign to window.location. However, it looks a bit unofficial.. in terms of
1. the member not being documented
2. not sure if the url member will exist in the future
3. the generated javascript is constructing an object dealing with ajax... and i'm just grabbing the URL member from it... it just feels... like a hack.
But i've tested this, and it works. See code below:
function patientResultsListClickHandler(personId) {
var fpersonId = personId;
return function() {
window.location=appRoutes.controllers.Application.entry(personId).url;
// window.location="/entry/" + fpersonId; // the sort of hard-coding of URL that
}; // I wanted to avoid, but don't seem able to.
}
Does anyone else have a better solution?

Debugging javascript functions

Is there a way in Firebug (or any other debugger) to see the functions that are being called as a page loads?
Edit: Breakpoint is really not what I'm looking for- I'd like to see the functions being called with the arguments that are being passed as I work on the page - something similar to the console - where I can see Http AJAX Post messages - with post values and the response.
Edit2: It looks like Profiler is something that I was looking for - but is there a way of looking at the parameters passed to the function and the return value?
You can always just print it out yourself. ( I know this may not be the answer you wanted.)
But what you can do is add a
<div id="debug"></div>
in your document.
Then add:
function log(str) {
$('#debug').append(str); // I'm using jQuery here
}
and then you can add the logs in your javascript, e.g.:
function myFunc(foo, bar, baz) {
log("myFunc called with ("+foo+", "+bar+", "+baz+")<br/>");
// your stuff
}
Tedious, but effective (IMO).
Firebug's console.log statement will dump stuff to the console for you, you just need to add console.log statements. For post requests and responses, use the net panel. Personally, I think adding a debug function and div to your page is overkill.
I think you need to make this more specific if you want to get more specific answers than "just use a breakpoint". Do you know what "code profiling" is? Is that what you want to do? You can google for "firebug profiler", and there is also some information right here on SO, e.g. Understanding Firebug profiler output

Categories

Resources