I have a form. I am trying to validate it through AJAX GET requests.
So i am trying to send the field values in the GET request data.
$('#uxMyForm').serialize();
the problem it is returning something undecipherable. I have used serialize before. This is totally bizzare.
the return value of serialize is
actionsign_upcontrollersitedataauthenticity_token=oRKIDOlPRqfnRehedcRRD7WXt6%2FQ0zLeQqwIahJZJfE%3D&customer%5BuxName%5D=&customer%5BuxEmail%5D=&customer%5BuxResidentialPhone%5D=&customer%5BuxMobilePhone%5D=&customer%5BuxDateOfBirth%5D=&customer%5BuxAddress%5D=&customer%5BuxResidentialStatus%5D=
i have no idea how to use this.
Thanks
update:
My question is how do i process such a request? like this?
puts params[:data][:customer][:uxName]
my GET request trigger looks like this
$.get('/site/sign_up',{data : $('#uxMyForm').serialize() }, function(data){
alert(data);
});
The above jquery lines generate the request.. on the action method i do the following
render :text => params
when i observe what is sent in the GET,in firebug PARAMS
**data** authenticity_token=oRKIDOlPRqfnRehedcRRD7WXt6%2FQ0zLeQqwIahJZJfE%3D&direct_customer%5BuxName%5D=&direct_customer%5BuxEmail%5D=&direct_customer%5BuxResidentialPhone%5D=&direct_customer%5BuxMobilePhone%5D=&direct_customer%5BuxDateOfBirth%5D=&direct_customer%5BuxAddress%5D=&direct_customer%5BuxResidentialStatus%5D=
the return value that i print in alert has
actionsign_upcontrollersitedataauthenticity_token=oRKIDOlPRqfnRehedcRRD7WXt6%2FQ0zLeQqwIahJZJfE%3D&direct_customer%5BuxName%5D=&direct_customer%5BuxEmail%5D=&direct_customer%5BuxResidentialPhone%5D=&direct_customer%5BuxMobilePhone%5D=&direct_customer%5BuxDateOfBirth%5D=&direct_customer%5BuxAddress%5D=&direct_customer%5BuxResidentialStatus%5D=
How does the form itself look. I have no experience with Ruby on rails - and if it builds the form in a new exciting way - but it looks as if there's only two form elements: authenticity_token and customer - where customer is an array of items. This is the data you posted, but I urldecoded it and put in some linebreaks:
authenticity_token=oRKIDOlPRqfnRehedcRRD7WXt6/Q0zLeQqwIahJZJfE=
&customer[uxName]=
&customer[uxEmail]=
&customer[uxResidentialPhone]=
&customer[uxMobilePhone]=
&customer[uxDateOfBirth]=
&customer[uxAddress]=
&customer[uxResidentialStatus]=
What you could do is to serialize the form to an array and clean it up before sending it using jQuery ajax request. I did something similar once when I had to serialize .net runat-server form elements:
var serializedData = $(form).serializeArray();
for( i=0; i < serializedData.length; i++)
{
// For each item in the array I get the input-field name after the last $ character
var name = serializedData[i].name;
var value = serializedData[i].value;
if( name.indexOf('$') != -1)
name = name.substr( name.lastIndexOf('$')+1 );
serializedData[i].name = name;
}
var ajaxPostData = $.param(serializedData);
So instad of blabla$ABCPlaceHolder$tbxEmail I got tbxEmail in the array. You could do the same to get uxName, uxEmail etc instead of the customer array.
Note then again, however, due to my inexperience with ruby that this may not be the best solution - maybe there's a setting you can change to build the HTML form differently?
Updated:
I'm not sure how ruby works, but after a googling I found you should be able to receive your values using params:customer as an array.
params:customer should contain an array of the values
{:uxName => "", :uxEmail => "" }
I hope that tells you something on how to receive the data. Maybe (warning - wild guess!) like this?
params[:customer][:uxName]
Related
I'm learning stimulus and trying to get add a checkbox feature where you can mark an order as complete from the show page without using a form. I followed this tutorial, but am not getting the correct results. The checkbox does nothing when clicked and unchecks when refreshed; however if I manually set the complete attribute to true, the checkbox is automatically checked when loading the page, as it should.
I have a model "Order" with a boolean attribute "complete". Here's my show.html.erb section
<tr data-controller="todo" data-todo-update-url="<%= order_path(#order.id) %>">
<td>
<div>
<input type="checkbox"
data-action="todo#toggle"
data-target="todo.completed"
<% if #order.complete %> checked <% end %> >
</div>
</td>
</tr>
Here's my stimulus todo_controller
import { Controller } from "#hotwired/stimulus"
export default class extends Controller {
static targets = [ "completed" ]
toggle(event) {
// Inside the toggle(event) function, let’s start by getting the value of the checkbox,
// and put it into a FormData object
let formData = new FormData()
formData.append("#order[complete]", this.completedTarget.completed);
// Let’s post that data to the "update-url" value we set on the Todo row.
// We’ll set the method to PATCH so that it gets routed to our todo#update on our controller.
// The credentials and headers included ensure we send the session cookie and the CSRF protection token and
// and prevent an ActionController::InvalidAuthenticityToken error.
fetch(this.data.get("update-url"), {
body: formData,
method: 'PATCH',
dataType: 'script',
credentials: "include",
headers: {
"X-CSRF-Token": getMetaValue("csrf-token")
}
})
// We can take the Response object and verify that our request was successful.
// If there was an error, we’ll revert the checkbox change.
.then(function(response) {
if (response.status != 204) {
event.target.complete = !event.target.complete
}
})
}
}
Can someone tell me where my code is going wrong?
This is more a long comment than a solution but few things I see :
You create an empty form and append a single input with name
"#order[complete]" though your Stimulus controller is Javascript
and has no knowledge of # the such way you use in Ruby. Also params
names are usually model[field] then I think you don't need the #.
"order[complete]" should be fine.
Also you grab the value from a specific target for the aforementionned value with this.completedTarget.completed. Should you not rather pick the value of the input field ? and rather grab this.completedTarget.value or maybe the checked status this.completedTarget.checked
You are getting the URL to your fetch from a data attribute. I am not a stimulus expert but it doesn't look like anything Stimulus related. As of now you have written it this.data.get("update-url") but in regular javascript, something like this.element.dataset.todoUpdateUrl should work.
And just to be sure there is no confusion to about where you will
call this , just declare it at the top of your Stimulus methd like
this : var backUrl = this.element.dataset.todoUpdateUrl. And fill the url to your fetch as just fetch(backUrl,...
you pass the formData directly to your fetch body. If this doesn't work, try to stringify it and extract the entries like : JSON.stringify(Object.fromEntries(formData)). Also I am not too sure about the dataType: 'script', you may just omit that alltogether.
There may be other problems that I don't see. Also when you are dealing with JS, don't only look to your Rails console, especially if nothing hits the backend. Open the developper / inspect tool in your browser and monitor the console there, you should see all the XHR (async) requests made to your app.
If nothing happens, then your fetch is not firing and there need to be more investigations made..
I am trying to insert data from a form built with Ruby on Rails to my SQL Server database. I have connected my database correctly and can pull data from it. I am now trying to post back to it. I am needing help with figuring out how to get the data from the form into the correct columns in my table in the database.
My ajax:
<script>
$('#Favorites').on('submit',function(event){
var $form = $(this),
data = $form.serialize();
var url = 'http://localhost:3000/welcome/insert';
$.ajax({
type: 'POST',
url: url,
data: data,
success: function(){
alert('Your form has been successfully submitted!');
document.getElementById('Favorites').reset();
window.location.reload();
},
fail:function(){
alert('something went wrong...try again');
}
});
return false;
});
</script>
My controller function:
def insert
#ipinsert=Ipdw.connection.execute("insert into [DB_Test02].[dbo].[My_Table] (Report_Name,Report_Link)
values ('I am cool','www.google.com')")
end
Currently I just have a dummy insert statement here to make sure that I can insert into the tables and I can. I just need to know how to break out the form values sent to the controller and how to tell Rails what table and columns to put those values into.
Rails will format the data for you. In controller like this:
{'Report_Name': 'some name', 'Report_link': 'www.example.com'}
and will be accessible via the params.
Your job is now to format the data correctly for the manual execution of the SQL query.
insert_values = "('%s', '%s')" % params['Report_Name'], params['Report_link']
#ipinsert=Ipdw.connection.execute("insert into [DB_Test02].[dbo].[My_Table] (Report_Name,Report_Link) values #{insert_values}")
For the problem of which table to add to your DB server you could specify this in hidden fields in your form and every fieled should have a name, When you say $form.serialize(); it turns it to something like FirstName=Amr&SecondName=Adel and so on where FirstName is the name of the field and Amr is the value of the field, Then you put this serialization into a form of JSON format like {"data": $form.serialize()} and add dataType: "JSON" to your post request, In your Insert function you can get it through params[:data] and split it with& to be something like ['FirstName=Amr','SecondName=Adel'] and every element split it with = so you can get something like this [['FirstName','Amr'], ['SecondName','Adel']].
Hope this helps.
I am sending a post to a controller / action (not ajax).
Inside the action, I am doing the standard way of checking to see if it was a post (the exact way works in other actions I am using).
if( isset( $_POST['LessonForm'] ) )
{
...
}
else
{
Yii::trace( "Post Not Set" );
}
And the post is always not set.
However, if I put a var_dump( $_POST ); die(); in front of the conditional, I get this:
array(2) { ["LessonForm"]=> array(3) { ["title"]=> string(4) "test" ["shortDescription"]=> string(4) "test" ["image"]=> string(0) "" } ["yt1"]=> string(0) "" }
So the post is clearly there. Furthermore,
foreach( $_POST as $key => $value )
{
echo( $key.'<br>' );
}
I get this:
LessonForm
yt1
Further suggesting the post is there.
When trying to use the variable in $_POST, it is not there. If accessing it in a foreach loop and assigning it to a variable, I can vardump the variable but not use it.
To test if it was a accessControl problem, I removed all filters.
What can block access like this?
Update:
#Stu is correct in that it is not being sent as a POST. The form method is post. Not sure how else to force a post?
Update 2:
Problem is fixed, but I'm still not sure what was causing the CActiveForm to send a get rather than post and still include post data.
After removing the transaction from the model save, the problem vanished (it should not have been there in the first place).
Update 3:
The original problem was an actionCreate. That problem mysteriously vanished. Next was an actionEdit. The view rendered (with the form) is the same file. The action was copied and pasted with modifications as to how the data was being saved and getting the model rather than making a new one.
After looking at the network traffic, there is a post followed immediately by a 302 redirect that isn't in my code. For some reason Yii is forcing a 302 redirect to get to the action.
Yii has already abstracted out getting request variables whether they're POST or GET
Use: Yii::app()->request->getParam('SomeVarName', 'ADefaultValue');
To get a request variable and returning a sensible default if one doesn't exist. If you're having trouble sending the variables from the form in the first place though, that could be a different issue.
I have a model appointment which has many tasks.
Creating a new appointment model which has tasks works fine with backbone. But when i try to update the model with the ids of different tasks it is not working.
I get the following error:
ActiveRecord::AssociationTypeMismatch: Task(#1192000) expected,
got ActiveSupport::HashWithIndifferentAccess(#2458300)
Parameters:
{"appointment"=>
{"id"=>"36",
"customer_id"=>"19",
"employee_id"=>"10",
"done"=>"",
"notes"=>"",
"starts_at"=>"2012-09-05 13:00:00 +0200",
"ends_at"=>"2012-09-05 14:30:00 +0200",
"bookingtype"=>"",
"tasks"=>
"[{\"created_at\"=>\"2012-09-04T13:37:17+02:00\",
\"duration\"=>\"60\", \"id\"=>\"12\",
\"task_category_id\"=>\"5\", \"updated_at\"=>\"2012-09-04T13:46:13+02:00\"}]",
"appointment"=>"",
"task_ids"=>"[\"12\"]"},
"action"=>"update",
"controller"=>"appointments",
"id"=>"36"}
I have some idea that the problem is that there is tasks and task_ids in the request but I have no idea how to fix that in backbone.
My update method looks like this:
save: function() {
var self = this;
var tasks = [];
$("input:checked").each(function() {
tasks.push($(this).val());
});
this.model.save({starts_at: this.$('#appointment_starts_at_modal').val(), employee_id: this.$('#employeeSelect').val(), customer_id: this.$('#customerSelect').val(),
"starts_at(5i)": this.$('#appointment_starts_at_5i_modal').val() ,
"ends_at(5i)": this.$('#appointment_ends_at_5i_modal').val(), task_ids: tasks}, {
success: function(model, resp) {
self.model = model;
self.close();
},
error: function() {
//new App.Views.Error();
}
});
return false;
},
From the error, it sounds like a ruby issue and I'm not familiar with ruby at all. But, with respect to Backbone, it shouldn't be a problem that you have a "tasks" and "task_ids" attribute in your appointment model. Backbone will happily send those over to your server as JSON data. Note however, that when working with nested collections in Backbone, the way you're passing the ids as an attribute outside of the task models is a bit odd. :-)
I can talk a little bit about what I see from a Backbone perspective though.
I'm assuming your tasks_ids attribute represents an array of ids of all the tasks you have. tasks is an array() of task JSON objects. In Backbone, when working with nested collections and such, usually the id attribute of each task would be part of the task object. So if I made an app that sent a bunch of tasks data as an array, it would send looking like this:
"tasks"=>
"[{\"id"=>\"12\", \"created_at\"=>\"2012-09-04T13:37:17+02:00\",
\"duration\"=>\"60\", \"id\"=>\"12\",
\"task_category_id\"=>\"5\", \"updated_at\"=>\"2012-09-04T13:46:13+02:00\"}]",
When I work with nested collections I basically make sure the ids and all attributes of some model are encapsulated by the object.
// My fake JSON
{'id':'1', 'appointment':{
'id':'50',
'tasks':[
{'id':'100', 'taskName':'groceries' /* etc. */},
{'id':'200', 'taskName':'bank errand'}
]
}}
When my appointment model receives this fetched data, I'll either process it in my parse() or modified set() method. I'll just demonstrate what I do with parse()
// Inside my appointment model definition
parse: function(response) {
if (_.isUndefined(this.tasks)) {
this.tasks = new TasksCollection();
}
this.tasks.reset(response.tasks);
delete response.tasks;
return response;
}
Something like the above. My TasksCollection would have model: Task defined so resetting with an attributes hash will populate my collection nested inside my appointment model with the appropriate data (with ids included.)
I don't think this solves your problem, but since you were alluding to the Backbone way of doing things I thought having this way (among many) illustrated might give you some ideas.
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