:remote => true/data-remote on a form loaded via ajax - ruby-on-rails-3

In my Rails app, I have a form that is loaded via Ajax using jQuery load method.
function load_sales_form(product_id) {
$("#sales_form").load("<%= url_for(:action => :show_sales_form) %>"/ + product_id);
}
The loaded form has a form_for tag with the :remote => true option and it does add the data-remote="true" attribute to the form.
But the form isn't submitted using Ajax when the user clicks the submit tag button. It works fine if the form is loaded in the standard, non-ajax way, but it the form is loaded via ajax after the document is ready, is does not submit using ajax, it submits as a standard form.
From what I studied so far, this happens because the rails.js file (which contains the stuff that allow data-remote forms to be submitted via ajax) does not apply it's features to html content loaded via ajax.
Is it possible to force rails.js file to apply it's features to content loaded via Ajax?

Same situation here. I found a solution.
Not the dynamic loading, but incorrect triggering of submit event was the cause in my case.
I had a Bootstrap modal with data-target and href attributes set. This causes the content inside a .modal-body to be loaded via AJAX from address specified in href.
The modal was pre-equipped with save button (outside of the loaded form), which called the submit like this.
$modal.find("form.loaded_form").get(0).submit(); // INCORRECT
The former only executes raw submit, but:
$modal.find("form.loaded_form").trigger('submit'); // CORRECT
does the trick.

Related

How do I submit a form to an MVC controller action using a blazor EditForm component?

Using blazor I would like to submit the form to an MVC controller action once validation has taken place. Can I make the form behave like a regular form? The following doesn't work because the action attribute is ignored.
<EditForm EditContext="#_modelContext" OnSubmit="HandleValidSubmit" action="/" method="post">
The form values tell the controller what file send to the response stream.
I don't see away to bypass the behaviour of EditForm. Is this possible?

ViewStateException - Validation of viewstate MAC failed - Sitefinity ASP.NET MVC with Jquery Mobile

I am getting this error most of the time when I submit my form. I am using Sitefinity 6.2 with ASP.NET MVC 4.0 and JQuery Mobile.
As I have Sitefinity in Hybred mode I am using the #Html.BeginFormSitefinity() command to create the form. On the Controller I have my action with the [HttpPost] attribute. The code always hits my default action on the controller with no problem. No matter what I put in the form when I submit I only get an error message on the page...never hits the HttpPost action.
I've looked around and there are many pages with fixes for the MAC failed issue, but none are working for me. I have a machine key in the web.config and I am NOT going to set enableViewStateMac to false as that is a security hole.
OK I tried working with both of the below solutions but they are both really bad. Here is what I am doing now, which is still not great, but I have Sitefinity, MVC, and JQuery Mobile all on the same page and forms are not giving me View State Exceptions anymore.
First thing is that adding data-ajax="false" is not enough, for this to work you need to disable Ajax before JQuery Mobile starts. So, to do this you need to add in this script BEFORE the JQuery Mobile File loads but after the JQuery file loads.
$(document).bind("mobileinit", function () { $.mobile.ajaxEnabled = false; });
After doing this I then do not use the Sitefinity Begin Form, I just JQuery to change the form on the main page to have the correct action.
<script>
$("#aspnetForm").attr("action", "Home/Login");
</script>
Together this means that there is a complete page load for each page change, and form posts use the form declared in my WebForms Master Page.
-Old Answer -
Actually...what I have below is not working. What I am
currently doing is really ugly but is usually working.
As long as the user enters the site from the home page then the home
page is the Jquery Mobile first page. The view state errors that I
was getting was because it saw the current page as the first page and
the form submit was to the active page. What if the controller for
the home page was just set to handle ALL HTTPPost calls? I have
removed the #Html.BeginFormSitefinity() from all the views with forms
and am just using the form on my top level masterpage. Then I add in
code on the view to change the action of this form to point to the
main page controller. ex
<script>
$("#aspnetForm").attr("action", "Home/Login");
</script>
Once I made this change the forms are not throwing view state
exceptions...as long as the home page is the Jquery Mobile first page.
If the user comes in from a different page then all is scrambled.
Don't have an answer for that yet.
Really Old Answer -
OK, think I have found it. I read somewhere, lost the link now, a
list of issues that can cause the error message. One of them is the
form being submitted from a different page.
I looked at the error message I was getting with Fiddler and noticed
that the Referer was my home page but the URL of the form post was the
URL for the page with my form. In stead of browsing through my site
to the page with the form I typed the URL in the address bar. I tried
submitting my form again and now it works!
So, this is an issue of Sitefinity and JQuery Mobile fighting it out.
When asp.net MVC is run in Hybred mode in Sitefinity it is actually
run in a Web.Forms master page that contains a form. When you use the
#Html.BeginFormSitefinity() to add a form to the view it is actually
just adding a div and then using AJAX to submit the form on the
Web.Forms master page.
JQuery Mobile loads up the first page that you visit, but later pages
are just injected into the existing page. So, there are multiple
data-role="page" divs loaded up in the DOM, inside of the Sitefinity
Web.Forms Master Page.
This all together is causing the form to post with the URL of the
active data-role="page" but the server sees that it is being refered
from the original page I loaded up. So, if I went to the page with
the form first all would work, start at any other page it does not
work.
Now that I know this I can put in data-ajax="false" on the link to the
page with the form and all looks to be working. This will cause
JQuery Mobile to not inject the target page into the current page but
will load all fresh with the target.
data-ajax="false" is the answer!

Yii - reload dynamically added CGridView

if append to page the CGridView ('myGridViewID') by ajax, I can't reload it.
$.fn.yiiGridView.update('myGridViewID');
TypeError: settings is undefined
$grid.addClass(settings.loadingClass);
Use renderPartial in controller action:
$cs = Yii::app()->clientScript;
$cs->reset();
$cs->scriptMap = array(
'jquery.js' => false, // prevent produce jquery.js in additional javascript data
);
// Look at 4th parameter: with TRUE value, your view will have additional javascript data.
$this->renderPartial('_partialViewWithGrid', array(), false, true);
Here is a wiki for dynamic CgridViews in the same view. That should work.
The problem with dynamically loaded CGridViews (and everything containing ajax) is that CController::renderPartial() does not render the required javascript code for them to work properly, unlike CController::render(), which includes the required layout and JS.
There is an extension called ZController which offers a workaround for this problem, but due to the way CGridviews are reloaded (by making an ajax call to the same URL)... when you try to filter/sort/page a CGridView loaded via AJAX, the subsequent Ajax call will replace the whole contents of your browser window, but I honestly think that maybe (only maybe) this workaround could help, but I haven't had the time to try it out.
That is why I currently avoid loading CGridViews using AJAX.

how can I use the fileupload helper when it is loaded in another page using the load jquery method?

I have the following problem, one page load in one of his div using the Load method from Jquery Ajax another page that use the FileUpload Asp.net Helper. Alone that page Works fine, but inside this div the upload button apparently calls the hosting page, not the page that original has the helper.
In consecuence, How can correctly use the helper loaded from another page?
In a scheme I think that this is happening:
And I want this to happen, but don't know how to do it:
The upload button submits the form. It will be submitted to whatever location is specified in the action attribute of the form. Therefore you should set the action attribute value to the page that you want the form to post to.
This will be easier to manage if you set includeFormTag to false. It is true by default:
#FileUpload.GetHtml(
initialNumberOfFiles: 1,
allowMoreFilesToBeAdded: false,
includeFormTag: false,
uploadText: "Upload",
name: "Upload1"
)
You will then need to provide your own form tag. Make sure you include the correct enctype for managing file uploads:
<form action="somePage" method="post" enctype="multipart/form-data">
...

Use JS to change <form> from remote to non-remote in Rails 3, HAML

The problem is that i have a remote form that, based on condition, id like to convert to a non-remote form (using UJS), and then submit.
note the form has a file upload.
Here's the details: I have initially rendered the remote form using
= form_for #myobj, :url => {:action=>"remoteAction", :controller=>"myobjects"}, :remote => true do |f|
... (f.fields....)
which produces the HTML:
<form id="new_myobj" class="new_myobj" method="post" accept-charset="UTF-8" data-remote="true" action="/remoteAction">
when i click submit, as expected, the form is submitted 'AS JS'.
in the controller action, i am doing some validation of the fields inside the submitted form.
If all the validations pass, i execute the following .js.haml template:
$('form#new_myobj').removeAttr("data-remote");
$('form#new_myobj').attr('enctype', 'multipart/form-data');
$('form#new_myobj').attr('action', '/myobjects/regularAction');
which successfully changes the HTML on the page (witnessed via Firebug) to:
<form id="new_myobj" class="new_myobj" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="/myobjects/regularAction">
since the form contains an f.file_field, i have to submit as multipart so the image can be uploaded, and i cannot submit 'AS JS'
now, when i click submit, the controller action 'regularAction' is indeed called, but its still 'AS JS'
the question is, what else do i need to change in the HTML so the form can be submitted non-xhr? is it related to the headers?
jQuery is a bit tricky with the data attributes since it both
reads the HTML5 data tags as well as its own storage bound to the
DOM element, that is also called data. When writing to an attribute
that value gets copied into jQuerys own data storage (presumably
when data("remote") is being called).
However, this only happens
if jQuery’s data is empty for that name. Thus setting the attribute will only work once, after that the "cached" value is being used
even if the attribute changes. In order to really get rid of the
value, we need to remove the attribute and jQuerys own storage
method in that order. The reason is that there’s a high-level
(element.removeData(…)) function and a low level one (jQuery.
removeData(element, …)). The former re-reads the HTML5 data
attribute and stores it in jQuery’s own storage. Using the rather
unusual low level function obviously works as well.
Also, we do really need to remove the attribute -- setting it to
false is not enough since Rails only checks if form.data('remote')
is not undefined (look for it in jquery_ujs.js).
TL;DR:
attr("data-remote") != data("remote")
These two lines make a form non-remote (again). Order matters.
$("form").removeAttr("data-remote");
$("form").removeData("remote");
It’s documented, if you actually know what you’re looking for:
http://api.jquery.com/jQuery.data/ (low level function)
http://blog.madebydna.com/all/code/2011/12/05/ajax-in-rails-3.html
StackOverflow doesn’t allow me to post more than two links, but you can guess the removeData one. The high-level functions are linked from the low level ones.
Avoiding the token authenticity error in Rails 4+:
As Stan commented below, just doing the above will fail with an InvalidAuthenticityToken error. The workaround is easy though, see here for details: https://stackoverflow.com/a/19858504/1684530
The problem is that your approach to disable the Ajax submission isn't quite correct. You need to unbind the JavaScript events that have already been added by rails.js (Rails UJS adapter) to the form.
You can do that by:
$('form#new_myobj').unbind() to unbind all events attached to the form. You also need to $('form#new_myobj').removeAttr('data-remote') and $('form#new_myobj').removeAttr('data-type') to remove data-remote and data-type attributes (if existent).