Using changePage to Open a Dialog - Data object not sent - jquery-mobile

$.mobile.changePage("verify.aspx", { transition: "pop", role: "dialog", data: $("#form1").serialize() });
I'm using the above syntax to open a dialog box and in trying to send the form data via the data argument, nothing is passed.
This is what's being passed in the query string when I open the dialog:
#&ui-state=dialog&ui-state=dialog
(as a side note, this call is originating from a button within another dialog, thus the two ui-state=dialog's)
As you can see, no form data. Any ideas what I can do to persist the data in the url?

Answering my own question:
Found that the data-url attribute of the dialog you request is injected w/ the relative url.
By doing something like:
$("#dialog").on("pagebeforecreate", function (evt) {
var urlObj = $.mobile.path.parseUrl($(this).attr("data-url"));
Will give you access to the url and thus the proper query string values.

Related

Rails Frontend Trying to save autogenerated data to database without form

I'm new to ruby on rails. I'm trying to save data that is generated by itself to the database. i have looked into and found I was meant to use ajax, however all the videos/forums i have seen are example of ajax that use form and not refreshing page. i want to save data automatically without pressing submit.
Assume that the project is fresh project with postgresql as the database. I have created a database that can hold geo points by using postgis. i have created another page where it has map implemented where i can manully pin location. I want to save the manuuly pinned location to the database.
function onMapClick(e) {
alert("You clicked the map at " + e.latlng);
}
mymap.on('click', onMapClick);
var popup = L.popup();
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(mymap);
}
mymap.on('click', onMapClick);
The e.latlng holds the geopoint, but i dont know how to save it the database if the user clicks anywhere on the map.
You don't need submit form to use ajax.
Basically what you want is add event listener to the map, and when user click then send ajax request to the controller.
For example, let's say that your map is inside div with id my-map.
If you use jQuery you can write something like this:
$('#my-map').on('click', function() {
# add your logic here
$.ajax({
url: 'your-url',
type: 'POST',
dataType: 'json',
contentType: "application/json; charset=utf-8",
data: JSON.stringify({
'let': data you want to send to backend
})
}
Hope it works!
EDIT:
After I looked your code I found that you can not have jQuery in your project so you can not use jQuery ajax. You need use vanilla javascript. So instead this snippet above, you can write this.
var xhttp = new XMLHttpRequest();
const params = { saving_location: { geoPoints: e.latlng } }
xhttp.onreadystatechange = function() {//Call a function when the state changes.
if(xhttp.readyState == 4 && xhttp.status == 200) {
alert(http.responseText);
}
}
xhttp.open("POST", "/saving_locations", true);
xhttp.setRequestHeader('Content-Type', 'application/json', 'Accept', 'application/json');
xhttp.send(JSON.stringify(params));
Also add protect_from_forgery with: :null_session in your application controller and skip_before_action :verify_authenticity_token in your Saving Location controller.(under before_action).
Here is good blog post why you need this https://blog.nvisium.com/understanding-protectfromforgery
Please notice that you wan't save your database, because your geoPoints type in database is type of point and you send string to rails controller. I never work with points in rails so I can not help you here.(You can always add two columns in db, one for longitude and one for latitude and then store numbers instead point)

MVC Web Api not getting called from javascript ajax

I have a Durandal/Hot Towel test app I'm trying to wire up. I have the below ajax call but I'm getting a 404 error.
GET http/.../api/Pizza/GetPizzasByOrderId?%22a8926610-a713-494c-bb15-46f6487a01c7%22 404 (Not Found)
I can manually change the url to:
http/.../api/GetPizzasByOrderId?orderId=a8926610-a713-494c-bb15-46f6487a01c7
It works. But I would like to know why the other call isn't working or more so, why is the ajax messing the parameter up in the URL and not as data like it does with complex objects. I have a get and a save that is working just fine. The get has zero params and the save is passing a complex object in.
C# Web Api Controller:
public class PizzaController : ApiController
{
[HttpGet]
public IEnumerable<Pizza> GetPizzasByOrderId(Guid orderId)
{
return DATA.GetPizzasByOrderId(orderId);
}
}
JAVASCRIPT:
var dataCall = $.ajax(config.getPizzasByOrderIdUrl, {
data: ko.toJSON(orderId),
type: "get",
contentType: "application/json"
});
Should I just change my JavaScript code to the below and be done with it or is there a better way to talk to the Api?
var getPizzasByOrderId = function (orderId) {
return Q.when($.getJSON(config.getPizzasByOrderIdUrl + "?orderId=" + orderId));
};
You could either use the code as you have it in that last code block, or you could pass in an object in place of your orderId as in the code block below. Either way, the difference is that the orderId parameter is being named.
var dataCall = $.ajax({
url: config.getPizzasByOrderIdUrl,
type: "GET",
data: {orderId : orderId},
});
In regard to why $.ajax() works fine for your POST, you can check this out pretty easily by running these two bits of code and viewing the requests that go across the wire. I recommend using google chrome.
Load a page that has jQuery loaded
Open the developer tools and go to the console
Enter the following code snippet
$.ajax("", {
data: {orderId: 123},
type: "get",
contentType: "application/json"
});
Switch to the network tab and click on the one that ends in ?orderId=123
Notice that it does have the data appended as query string parameters
In the snippet above, replace the "get" with "post"
After you hit enter, you should see another request on the network tab of the developer tools.
Notice that when changing nothing but the request type, the data is moved from the query string to the body. As noted in the comments, WebApi will pull from the body of the request and use the model binder to populate the complex object.

Grails file download does not initiate when called from remoteFunction

In my Grails application, a user can click on a g:link which will call my controller to export certain data to a CSV file. This works with no problems.
I then moved that button to a jQuery dialog box and, when the button is clicked, I use
${remoteFunction(action:'export', onSuccess:'closeMe();', id:courseInstance?.id)}
to call the same controller method and close the dialog box. I've confirmed that the method is actually called, and the dialog box closes. The user is not prompted with the CSV dowmload, however. I'm assuming this has something to do with the remoteFunction, but I'm not really sure. Can anyone explain why this might happen, and a potential fix?
Thanks!
With AJAX requests you can't handle to download content as attachment and so it can't trigger the Save As dialog.
There are a couple of workarounds for this:
Use a plain g:link as before and bind the 'closeMe();' function to the 'click' event. The problem is that you have no control on error or success response.
Use an iframe: You can create a temporary invisible iframe and set its location to the URL of the file to download. It also has the backside of not controlling the success/error response.
The code could be the same as in this answer:
<script type="text/javascript">
function downloadURL(url) {
var iframe;
var hiddenIFrameID = 'hiddenDownloader';
iframe = document.getElementById(hiddenIFrameID);
if (iframe === null) {
iframe = document.createElement('iframe');
iframe.id = hiddenIFrameID;
iframe.style.display = 'none';
document.body.appendChild(iframe);
}
iframe.src = url;
}
</script>
And the link
Export

Transforming data returned while using jQuery's Autocomplete function

I'm trying to use the Autocomplete plugin to produce a search box similar to the one at IMDB, I want it to:
Show more than just text in the options.
To act like a link when an option is selected (as each option will be a unique record).
That, if the user chooses, they press the button and a search is performed on their input.
The docs say that there are 3 types of datasource it will work with:
A data source can be:
an Array with local data
a String, specifying a URL
a Callback
I can get the autocomplete to work with the 2nd option, but then there isn't the ability to transform the data returned, it just takes the JSON and puts it straight in the dropdown. This means the source url can only return data in the format {label: "blah", value: "blurg"}.
If I could inject a transformation function, then I could have the url return whatever JSON I like, the function would change the data into the format the autocomplete expects but also formatted as I wish, and all without changing the response served by the url (I'm not going to return HTML from there, only JSON).
e.g. The url could return this:
{ label:"Grosse Point Blank", id: 3, img:"/imgs/gpb.png",...}
and a transform function could mung it into something like this:
{ label:"<a href='/films/3/grosse-point-blank'><img src='/imgs/gpb.png' />Grosse Point Blank</a>", value="grosse-point-blank"}
I've tried using option 3, a callback, with a getJSON call, but I can't get it to work. The nearest code I've found to what I may need is here, but it has options that aren't listed in the current docs for Autocomplete and I don't understand how to use the response object.
Is there an example of using the callback method with an AJAX request, or how I can inject a function that transforms the code?
You can use the _renderItem() private method of autocomplete to format the return data. It looks like this:
$("#element").autocomplete({...}).data( "autocomplete" )._renderItem = function( ul, item ) {
//...
};
You can see the method definition here https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js#L520
An example of code that I have used:
$("#element").autocomplete({...})
.data("autocomplete")._renderItem = function( ul, item ) {
return $( "<li></li>" ) // create the list item
.data( "item.autocomplete", item ) // save the data to the DOM
.append( "<a>"+ item.label + "</a>" ) // add the HTML
.appendTo( ul ); // append to the UL
};
Here's a brief structure when using callback method.
source: function( request, response ) {
$.ajax({
...
success: function( data ) {
// do transformation of data here
response(data);
}
});
}
Quoted from your link, http://api.jqueryui.com/autocomplete/#option-source
The third variation, the callback, provides the most flexibility, and
can be used to connect any data source to Autocomplete. The callback
gets two arguments:
A request object, with a single property called "term", which refers
to the value currently in the text input. For example, when the user
entered "new yo" in a city field, the Autocomplete term will equal
"new yo".
A response callback, which expects a single argument to
contain the data to suggest to the user. This data should be filtered
based on the provided term, and can be in any of the formats described
above for simple local data (String-Array or Object-Array with
label/value/both properties). It's important when providing a custom
source callback to handle errors during the request. You must always
call the response callback even if you encounter an error. This
ensures that the widget always has the correct state.

jQuery Dialog posting of form fields

I'm trying to do some data entry via a jQuery modal Dialog. I was hoping to use something like the following to gather up my data for posting.
data = $('#myDialog').serialize();
However this results in nothing. If I reference just the containing form instead myDialog then I get all the fields on the page except those within my dialog.
What's the best way to gather up form fields within a dialog for an AJAX submission?
The reason this is happening is that dialog is actually removing your elements and adding them at root level in the document body. This is done so that the dialog script can be confident in its positioning (to be sure that the data being dialog'd isn't contained, say, in a relatively positioned element). This means that your fields are in fact no longer contained in your form.
You can still get their values through accessing the individual fields by id (or anything like it), but if you want to use a handy serialize function, you're going to need to have a form within the dialog.
I've just run into exactly the same problem and since I had too many fields in my dialog to reference them individually, what I did was wrap the dialog into a temporary form, serialize it and append the result to my original form's serialized data before doing the ajax call:
function getDialogData(dialogId) {
var tempForm = document.createElement("form");
tempForm.id = "tempForm";
tempForm.innerHTML = $(dialogId).html();
document.appendChild(tempForm);
var dialogData = $("#tempForm").serialize();
document.removeChild(tempForm);
return dialogData;
}
function submitForm() {
var data = $("#MyForm").serialize();
var dialogData = getDialogData("#MyDialog");
data += "&" + dialogData;
$.ajax({
url: "MyPage.aspx",
type: "POST",
data: data,
dataType: "html",
success: function(html) {
MyCallback(html);
}
});
}
Form element inside dialog is removed from form and moved to the end of the body. You need something like this.
$("#dialog_id").dialog().parent().appendTo($("#form_id"));
jQuery("#test").dialog({
autoResize:true,
width:500,
height:600,
modal: true,
bgiframe: true,
}).parent().appendTo("form");
This works like charm

Resources