Requests for a form that submits through ajax multiply with each subsequent submit - ruby

I have a form that makes an ajax request, the problem is that every time I click on it, the amount of times it makes that request multiplies.
Now I'm sure it's because of the way I've set up submit-intercept but I don't know how else to do it whilst still encapsulating it as a single component.
I'm using react as my view layer and I've attached a function that contains code to intercept the request and this function is called in both the afterMount callback and the after_update callback; if I don't do this then either the form submit is never intercepted or it only intercepts it once and then just does a normal submit.
Now obviously it's multiplying because those events fire and add an extra submit-handler.
I'm using opal and react.rb so the code might look a little odd.
Here's my function that intercepts the submit action on the form
def set_up_login_form
puts 'setting up form'
login_form = Element["#login_form"]
login_form.on :submit do |event|
unless login_state == :processing
event.prevent_default
username = login_form.find('#username').value
password = login_form.find('#password').value
login!
self.username = username
self.handle_login_submit({username: username , password: password})
end
end
end
Here are my call backs:
after_mount do
fix_button #untill materialize.js gets fixed
set_up_login_form
end
after_update do
set_up_login_form
end
I was able to reduce the amount of requests made by checking if the component state was already in the middle of a request, whilst this doesn't reduce the amount of submit handlers being added it does stop a good amount from doing anything, but it doesn't stop the actual multiplying of handlers being added.

I don't know why I didn't think of it till a colleague mentioned it but by moving the form to a sub-component I can now run the intercept code on the form components mount which only happens when it's rendered so problem solved!

Related

How rails form instance works?

I have these two methods, show and create.
def show
#article = Article.find(params[:id])
#comment = Comment.new
#comment.article_id = #article.id
end
def create
#comment = Comment.new(comment_params)
#comment.article_id = params[:article_id]
#comment.save
redirect_to article_path(#comment.article)
end
Show method displays my comment form.
In the show method why do we create a new instance of Comment and also associate the comment
instance to an article id.
Create method actually handles the submission of form.
In the create method, again i am creating a new comment object and again associating the comment's article_id.
My whole questing is why were repeating these things?. Why do I have associate my comment form with article_id when I am displaying it and again I am repeating the steps while submitting the form too.
This repetition could be avoided if you keep those resources nested and build the form as:
<%= form_for(#article, #article.comments.build) do |f| %>
Hope this helps! :)
The reason that you initialize a comment both times is because the user's browser only sees the html form - it doesn't have a concept of a Comment - and because each request to a Rails application is independent - nothing is persisted in the application between requests:
When the user requests the show page for an Article, the request is handled by the application something like this:
The controller creates a new Comment object (in memory).
The form_for helpers in the view build a form from that Comment.
The html for the show page is sent to the user's browser.
At this point the application has done everything it needs to serve this request, so the temporary Comment object is deleted.
When the user submits the form, the values that were entered are sent to the application in the comment_params and the application handles this request like this:
The controller creates a new Comment object (again in memory), but initializes it with the data that the user sent through in comment_params.
The controller saves the Comment - this stores the Comment in the database so it can be loaded later.
The controller redirects back to the show page.
Saving to the database is the main way that the application can persist things between requests - objects in memory only exist while the request is being processed.

django, return to previous page after form POST submit

In my web page I have a form that is being filled with data after some ajax requests. For example when a user chooses an item from the list, a simple ajax request is sent to the database that the item has been selected (but not confirmed, yet). Then the list on the web page reloads using a simpe ajax request (just the list, not the whole page) to fetch the new item list.
I think this is more or less a classic cart implementation.
However, when the user presses submit (classic form POST submit, not ajax POST for some reasons concerning the implementation) to confirm the whole list, I would like to return to the current page. (Current page varies) Is this possible? I am using django.
Thanks.
You can supply a next GET parameter when submitting the form, similar to django.contrib.auth's login() method:
https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.views.login:
<form action="/url/to/post/form/?next={{ some_variable }}">
where the variable can simply be the current URL (taken from the request) or a generated URL. In the view processing the form, simply check for a next parameter and redirect appropriately:
from django.shortcuts import redirect
if 'next' in request.GET:
return redirect(request.GET['next'])
You may be able to use the Post/Redirect/Get Design pattern (PRG). For more general information about Post/Redirect/Get please see the following: http://en.wikipedia.org/wiki/Post/Redirect/Get There are some nice process flow diagrams there.
A generic example of a view implementing PRG might look like the following:
# urls.py
urlpatterns = patterns('',
url(r'^/$', views.my_view, name='named_url'),
)
# forms.py
class MyForm(forms.Form):
pass # the form
# views.py
def my_view(request, template_name='template.html'):
""" Example PostRedirectGet
This example uses a request context, but isn't
necessary for the PRG
"""
if request.POST:
form = MyForm(request.POST)
if form.is_valid():
try:
form.save()
# on success, the request is redirected as a GET
return HttpResponseRedirect(reverse('named_url'))
except:
pass # handling can go here
else:
form = MyForm()
return render_to_response(template_name, {
'form':form
}, context_instance=RequestContext(request))
If you need to do something more interesting with the GET, reverse can take args and kwargs. Manipulate the view params, url_pattern, and reverse call to display the results you would like to see.
One additional note is that you don't have to redirect to the same view (as this example does). It could be any named view that you would like to redirect the user to.
current page is a very vague term but i am assuming you want the page that referred you to the form page, this is normally (not always) stored in the HTTP_REFERRER header of the request itself. You could try to fetch that from the request and do a redirect.

Sinatra - How to best move variable/parameter between pages

I have a register page with the usual email,name,password ..which is validated in the server's submitted route/page. if it fails then I redirect back but I want to fill the values back in the register page..I can put the register form parameters in the session but it will stay there...is there a page memory(a smaller scope than session) just like session which will be just for the next page and then gone/ which is the best way to implement this.
Thanks
Why don't you just render the registration page from the POST route like this:
post '/register' do
#registration_data = params[:stuff] # store all your registration data
if info_validates # everything validates
redirect './user_home'
else # something fails validation
haml :register # or erb or whatever your template engine is
end
end
Then in your view, have it fill in #registration_data if it exists.
Also, you can clear session data with session.clear.
Ajax validation would be much easier. You just register an onclick event to your form submit button that makes a call to a page that returns a json status code with the error information or 200 for OK. If 200, then submit.

Django Forms - Processing GET Requests

We have an existing Django form that accepts GET requests to allow users to bookmark their resulting query parameters. The form contains many fields, most of which are required. The form uses semi-standard boilerplate for handling the request, substituting GET for POST:
if request.method == 'GET':
form = myForm(request.GET)
if form.isValid()
# Gather fields together into query.
else
form = myForm()
The problem is that the first time the form is loaded, there's nothing in the GET request to populate the required fields with, so most of the form lights up with 'missing field' errors.
Setting initial values doesn't work; apparently, the non-existent values in the GET request override them.
How can we avoid this? I'm pretty certain we're simply not processing things correctly, but I can't find an example of a form that handles GET requests. We want errors to show up if the user hits the "Submit" button while fields are blank or otherwise invalid, but don't want these errors showing up when the form is initially displayed.
The positional argument to the forms.Form subclass informs Django that you intend to process a form rather than just display a blank/default form. Your if request.method == 'GET' isn't making the distinction that you want because regular old web requests by typing a URL in a web browser or clicking a link are also GET requests, so request.method is equal to GET either way.
You need some differentiating mechanism such that you can tell the difference between a form display and a form process.
Ideas:
If your processing is done via. AJAX, you could use if request.is_ajax() as your conditional.
Alternatively, you could include a GET token that signifies that the request is processing. Under this example, first you'd need something in your form:
<input type="hidden" name="action" value="process_form" />
And then you can look for that value in your view:
if 'action' in request.GET and request.GET['action'] == 'process_form':
form = myForm(request.GET)
if form.is_valid():
# form processing code
else:
form = myForm()
I'll also give you the standard, boilerplate point that it's generally preferable not to use GET for form processing if you can help it (precisely because you run into difficulties like this since you're using an anomalous pattern), but if you have a use case where you really need it, then you really need it. You know your needs better than I do. :-)
If your clean page load doesn't have any non form GET params, you can differentiate between a clean page load and a form submit in your view. Instead of the usual
form = YourForm()
if request.POST:
you can do
if request.GET.items():
form = YourForm(request.GET)
if form.is_valid():
...
else:
form = YourForm()
If your clean page load could have other params (eg email link tracking params) you'll need to use the QueryDict methods to test if any of your form params are in the request.
request.GET is and empty dictionary when you first load a clean form. Once you have submitted the form, request.GET will be populated with your fields data, even if the fields contain only empty data.
My first question is this, which I posted as comment:
Why not just use request.POST and the standard way of processing form data?
After considering everything here, perhaps what you are looking for is a way of processing data in your query string to populate a form. You can do that without using request.GET as your form.data.
In my own views, I take advantage of a utility function I created to add initial data to the form from request.GET, but I am not going to share that function here. Here's the signature, though. initial_dict is typically request.GET. model_forms is either a single ModelForm or a list of ModelForm.
def process_initial_data(model_forms, initial_dict):
Nevertheless, I am able to process the form through the standard practice of using request.POST when the form is POSTed. And I don't have to pass around all kinds of information in the URL query string or modify it with JavaScript as the user enters information.

First time jQuery $.post takes an extraordinarily long time, subsequent times normal

On a webpage we have the following system of server side form validation. For example, if the user is adding date-details for an event (and an event can contain many such date-details), we call a javascript function on click of the 'Add' button like below.
validateForm('frmName','codelibrary/classes/myclass.php','validationArrName')
where:
#frmName = form name
#codelibrary/classes/myclass.php = location of class file, that contains classes and functions for server side validation
#validationArrName = Type of validation we apply
In the php script, validationArrName is defined as a list of keys (representing form fields) and values (representing the functions we will call to validate that form field).
validationArrName = array ('fieldName1'=>validationFun1,'fieldName2'=>validationFun2);
eg:
fieldName1 = email_address
validationFun1 = validateEmail()
On the html page, we call the server side validation through ajax as follows.
$.post(className,$("form[name="+formName+"]").serialize()+"&isValidate=1&validateArrayName="+validateArrayName,function(data){ ... });
If the validation function reports an error, we display an appropriate error message back on the html page.
The problem is that when we do this for the very first time (eg: after a hard refresh of the page), submitting this date-details form for validation takes a lot of time, as compared to subsequent requests.
We observed that instead of calling the codelibrary/classes/myclass.php file once, it actually refers to this file more than 10 times before jumping to the required location (validationArrName) and running that.
For subsequent requests, it works fine and refers to that file only once.
What could be the issue here? Could there be an issue with our usage of jquery submit ?
the best thing you can do is time stuff.
in javascript:
console.time('post load'):
$.post(className,$("form[name="+formName+"]").serialize()+"&isValidate=1&validateArrayName="+validateArrayName,function(data){
console.timeEnd('post load');
console.log('data');
...
});
in php, use microtime to time different part and echo them. they will be printed in the console.
It should not be cache or include related, as ajax starts a new connection each time.
Following your comments, I edit this answer:
I'm still at loss of what happens. However I see two possibilities. The first one is that you use a "flag" to validate forms or not. When you load the page, all forms flag are unset, and first submit check them all. Subsequent submits works correctly.
Another option is that the first time you submit a form, you dont event.preventDefault() on the submit click, but it's still a loosy explanation.
I would love to see how you call the $.post(...) function (how the submit button is binded, or how $().submit() is called).

Resources