jQuery Dialog posting of form fields - jquery-ui

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

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)

How can I persist newly saved values across components? Pulling original values from DOM

I have 3 different components with buttons to navigate across them. All of the default form values are pulled from the DOM and set into the data beforeMount. The reason I'm doing it this way is that the values are coming from my Rails database.
When I edit a form and save it successfully (via ajax), everything is good but once I switch components using the navigation, those values in the inputs are reset back to the original/old values since the beforeMount is running again and the DOM was not updated with the new value (due to no refresh yet).
I tried changing the original values in the DOM with jQuery upon every update but that didn't work. It would work once but further updates didn't change.
Here is how I'm setting the data inside of the beforeMount:
const element = document.getElementById('setting');
const setting = JSON.parse(element.dataset.setting)
this.discountType = setting.discount_type;
Then, upon every ajax request I tried to edit those original values in the DOM which didn't work:
outerThis = this;
Rails.ajax({
url: '/update-settings',
type: 'POST',
data: data,
dataType: 'json',
success: (data) => {
ShopifyApp.flashNotice('Successfully updated')
var settings = $('#setting').data('setting')
settings.discount_type = outerThis.discountType
},
error: (err) => {
ShopifyApp.flashError('There was an error')
}
})
What's the recommended way to go about this issue?

jquery mobile 1.4 not updating content on page transition

From the index page, a user clicks a navigation link, the data attribute is passed via ajax, the data is retrieved from the server but the content is not being updated on the new page.
Been stuck for hours, really appreciate any help!
js
$('a.navLink').on('click', function() {
var cat = $(this).data("cat");
console.log(cat);
$.ajax({
url: 'scripts/categoryGet.php',
type: 'POST',
dataType: "json",
data: {'cat': cat},
success: function(data) {
var title = data[0][0],
description = data[0][1];
console.log(title);
$('#categoryTitle').html(title);
$('#categoryTitle').trigger("refresh");
$('#categoryDescription').html(description);
$('#categoryDescription').trigger("refresh");
}
});
});
Im getting the correct responses back on both console logs, so I know the works, but neither divs categoryTitle or categoryDescription are being updated. I've tried .trigger('refresh'), .trigger('updatelayout') but no luck!
This was not intended to be an answer (but I can't comment yet.. (weird SO rules)
You should specify in the question description that the above code IS working, that your problem occurs WHEN your playing back and forth on that page/code aka, using the JQM ajax navigation.
From what I understood in the above comment, you're probably "stacking" the ajax function every time you return to the page, thus getting weird results, if nothing at all.
Is your example code wrapped into something ? If not, (assuming you use JQM v1.4) you should consider wrapping it into $( 'body' ).on( 'pagecontainercreate', function( event, ui ) {... which I'm trying to figure out myself how to best play with..
Simple solution to prevent stacking the ajax definition would be to create/use a control var, here is a way to do so:
var navLinkCatchClick = {
loaded: false,
launchAjax: function(){
if ( !this.loaded ){
this.ajaxCall();
}
},
ajaxCall: function(){
// paste you example code here..
this.loaded = true;
}
}
navLinkCatchClick.launchAjax();

Using changePage to Open a Dialog - Data object not sent

$.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.

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.

Resources