Prevent Ajax.BeginForm from HTML encoding output - html

#using (Ajax.BeginForm("Create", "Comment",
new AjaxOptions
{
UpdateTargetId = "newComment",
OnSuccess = "function() { alert('finished " + ViewData.Model.Id + "'); }",
}))
{
...
}
outputs the following markup:
<form action="/Comment/Create" data-ajax="true" data-ajax-mode="replace"
data-ajax-success="function() { alert('finished 34'); }"
data-ajax-update="#newComment34" id="form1" method="post">
As you can see, it has HTML encoded my javascript. How do I prevent this?
EDIT: I have multiple AJAX forms on my page so the onsuccess function needs to know which one called it. In my code, you can see I am trying to pass state to this function. If OnSuccess can only take a function name (and not state), then how can I achieve this?

Personally I would use a standard Html.BeginForm helper with HTML5 data-* attributes that I will AJAXify myself:
#using (Html.BeginForm(
"Create",
"Comment",
FormMethod.Post,
new { data_id = Model.Id }
))
{
...
}
which outputs:
<form action="/Comment/Create" data-id="some id here" method="post">
...
</form>
and then in a separate javascript file I would subscribe for the .submit event:
$(function() {
$('form').submit(function() {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
dataId: $(this).data('id'), // <- pass the data-id HTML5 attribute
success: handleSuccess
});
return false;
});
});
function handleSuccess(result) {
$('#newComment').html(result);
// fetch the data-id of the form that trigerred the AJAX request
var id = this.dataId;
// TODO: do something with this id
}
I prefer this technique compared to the Ajax.* helpers as it gives me all the control I might need. Another advantage is that we get a clear separation between script and markup making the code nice and tidy.

Don't.
The HTML encoding is correct behavior, and the attribute value (as seen from Javascript code) will not be encoded.

I believe that It's because MVC interprets the OnSuccess (and other vars) as the name of a Javascript function and not a bit of Script.
Make a helper function that performs the script you want to act on the submit.

Related

Laravel 5.4: Submit a HTML form and receive a JSON response

Question: how can I communicate JSON back from a controller to my html page, and embed the response in my page, instead of destroying the page?
The long story is like this:
Embedded in a quite large html page (created by a view when I open my base URL, say, http://.../home) I have a html form. It has some data fields, and the usual "Submit" button.
<form class="form-horizontal" method="POST" action="{{ route('form.user') }}">
{{ csrf_field() }}
... lots of input fields ...
<div class="form-group">
<button type="submit" class="btn btn-primary">
Submit
</button>
</div>
</form>
The receiving route ...
Route::post('form/user','ItemController#save')->name('form.user');
And the controller ...
public function save(Request $request) {
...
return response()->json(['status' => 'Saved successfully']);
}
The whole thing works like intended, if I fill the form and hit the "Submit" button, the controller receives all input fields via the $request properties.
The problem arises after the return from the controller, the html is cleared from the browser, and the JSON is displayed.
What I need is receive the JSON and display it in a div of my original html, not replace it.
Question: what do I need to do, how can I hook into the communication to intercept and handle the JSON response, so I can display the response text in my original web page (using JQuery), and not destroy the html?
Thx, Armin.
Capture the FORM submit event, and prevent the default.
Construct an AJAX request
Dictate the response type.
Convert the form data to a serialized object to be sent to the server
Capture the returned response and apply it to a DIV.
That would look something like this:
$('form').on('submit', function(e){
e.preventDefault(); //1
var $this = $(this); //alias form reference
$.ajax({ //2
url: $this.prop('action'),
method: $this.prop('method'),
dataType: 'json', //3
data: $this.serialize() //4
}).done( function (response) {
if (response.hasOwnProperty('status')) {
$('#target-div').html(response.status); //5
}
});
});

How do i get input form value without submitting it?

I want the input value from user without submitting any thing then i want to pass it through ajax method as parameter to action method. I tried many method but i could not found a solution.
Here is the code
<input type="text" id="task" name="task" value="" />
#Ajax.ActionLink("ADD TASK", "show_task",new {task=Request["task"]}, new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "print",
InsertionMode = InsertionMode.Replace
})
Here is the controller action method
public ActionResult show_task(string task)
{
var add_task = new tasks_table();
add_task.task = task;
add_task.id = 24;
add_task.f_id=10;
add_task.date_oftask=DateTime.Now;
db.tasks_table.Add(add_task);
db.SaveChanges();
var tasks = db.tasks_table.Include(t => t.user_detail);
return PartialView("render_tasks",tasks);
}
Since you want the current value of the textbox, you may better do it yourself with your own javascript code to make the ajax call, instead of relying on the Ajax.ActionLink helper method.
So change your Ajax.ActionLink call to a normal action link.
<input type="text" id="task" name="task" value="" />
#Html.ActionLink("Add Task","show_task", null, new {id="addTask"})
<div id="print"></div>
Now listen to the click event on this link, read the value of the text box and send that to your server. You may use jQuery $.post method to do so. In the response callback, you can update the print div's content with the response coming back from your server.
$(function(){
$("a#addTask").click(function(e){
e.preventDefault();
$.post($(this).attr("href"), { task:$("#task").val()},function(res){
$("#print").html(res);
});
});
});
You can use JavaScript focusOut function to send the value to controller.
by focusOut method, we get the value in input field instantly when we moved to next field.
$('#task').focusOut(function(){
Your ajax call method....
});
Hopes it helps.

HTML post method vs AngularJS

I want to use AngularJS in my application, and at the initial stage I followed plain HTML for front view and for the back end potion I used a servlet and an ejb class where I organized SQL querys following CURD application method and that works really fine. Then I applied AngularJS that includes an Ajax call inside the $scope method. Once I create an Ajax method named "btnadd()", but now I cannot pass a value because the page directs to a servlet. Can any one help me to
<html ng-app="helloApp">
</head>
<body>
<div ng-controller="demoApp">
<form name="frm" method="post" action="Srvlet">
<input type="submit" name="btnadd" value="Add" ng-click="btnadd()"/>
My method in the JS file:
$scope.btnadd = function() {
$.ajax({
url: 'Srvlet',
type: "POST",
data: {
datepicker: $scope.newcontact.datepicker,
eId: $scope.newcontact.eId,
name: $scope.newcontact.name, `enter code here`
cmp: $scope.newcontact.cmp
},
success: function(data, textStatus, jqXHR) {
console.log(data);
$scope.$apply(function(){
$scope.newcontact.addRecordResult = data.addRecordResult;
});
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('Error : ' + jqXHR.responseText);
}
}); if($scope.newcontact.eId == null) {
$scope.newcontact.eId = departmentID++;
$scope.Departments.push($scope.newcontact);
} else {
for(i in $scope.Departments) {
if($scope.Departments[i].eId == $scope.newcontact.eId) {
$scope.Departments[i] = $scope.newcontact;
}
}
}
$scope.newcontact = {};
};
Hello and welcome on stackoverflow
I assume that the method btnadd() is attached to a submit button in which case it will proceed to the action. There is few possible solutions i.e. change submit button to standard button that wont send form but will call the method or/and add onsubmit="return false;" to form which will prevent form from sending
Although why don't you use an angularjs $httpinstead of jQuery?
https://docs.angularjs.org/api/ng/service/$http

How to send form field value to a REST service using JSON or AJAX

I have a form field (email signup) on the site, and the email provider wants me to submit it to their REST web service and get a response. I've never used JSON or AJAX before so floundering!
The HTML:
<form>
<input type="hidden" name="gid" value="12345678">
<input type="hidden" name="user.CustomAttribute.NewsletterPopUp" value="Global">
<input type="hidden" name="user.CustomAttribute.NewsletterOptIn" value="True">" value="True">
<input type="text" name="uemail" class="email_input_field" value="please enter your email" size="30" maxlength="64" onFocus="clearText(this)">
<input type="submit" name="signup" value="signup" class="email_submit_button">
</form>
Currently, using Javascript and using window.location to visit the URL (which creates the action instead of posting it) they want it converted to a form post action with XML response. What happens now:
$(".email_submit_button").click(function(){
var uemail = $('.email_input_field').val();
window.location = "http://example.com/automated/action.jsp?action=register&errorPage=/automated/action.jsp&gid=12345678&uemail="+uemail+"&user.CustomAttribute.NewsletterPopUp=Global&user.CustomAttribute.NewsletterOptIn=True";
return false;
}
});
I see you'r using jQuery so you can use the $.post to post to the server like this:
var url = "http://example.com/automated/action.jsp"
var data ={
"gid": form.gid,
"action": register,
"uemail": form.uemail,
"errorPage": "/automated/action.jsp",
"user.CustomAttribute.NewsletterOptIn": user.CustomAttribute.NewsletterOptIn,
"user.CustomAttribute.NewsletterPopUp": user.CustomAttribute.NewsletterPopUp
};
var success_func = function(data){
//do what you want with the returned data
};
$.post(url, data, success_func);
Documentation for $.post.
Or you can use the pure longer Ajax version it's mentioned in the documentation of the $.post.
EDIT:
I forget you can't do xhttpresuext to a different domain you need to use JSONP, here's a link to another SO post explaining everything by detail
Hope this help.
$(".email_submit_button").submit(function(e) {
// stop form from submitting
e.preventDefault();
// Grab all values
var uemail = $('.email_input_field').val();
// make a POST ajax call
$.ajax({
type: "POST",
url: "YOUR URL", // set your URL here
data: {
uemail: uemail // send along this data (can add more data separated by comma)
},
beforeSend: function ( xhr ) {
// maybe tell the user that the request is being processed
$("#status").show().html("<img src='images/preloader.gif' width='32' height='32' alt='processing...'>");
}
}).done(function( response ) {
// do something with the received data/response
//$("#status").html(response);
});
});
Not sure if ".email_submit_button" is the class given to the submit button or the form.. you need to use the id or class given to the form and not the submit button.. hope this helps

Using PUT method in HTML form

Can I use a PUT method in an HTML form to send data from the form to a server?
According to the HTML standard, you can not. The only valid values for the method attribute are get and post, corresponding to the GET and POST HTTP methods. <form method="put"> is invalid HTML and will be treated like <form>, i.e. send a GET request.
Instead, many frameworks simply use a POST parameter to tunnel the HTTP method:
<form method="post" ...>
<input type="hidden" name="_method" value="put" />
...
Of course, this requires server-side unwrapping.
XHTML 1.x forms only support GET and POST. GET and POST are the only allowed values for
the "method" attribute.
Can I use "Put" method in html form to send data from HTML Form to server?
Yes you can, but keep in mind that it will not result in a PUT but a GET request. If you use an invalid value for the method attribute of the <form> tag, the browser will use the default value get.
HTML forms (up to HTML version 4 (, 5 Draft) and XHTML 1) only support GET and POST as HTTP request methods. A workaround for this is to tunnel other methods through POST by using a hidden form field which is read by the server and the request dispatched accordingly. XHTML 2.0 once planned to support GET, POST, PUT and DELETE for forms, but it's going into XHTML5 of HTML5, which does not plan to support PUT. [update to]
You can alternatively offer a form, but instead of submitting it, create and fire a XMLHttpRequest using the PUT method with JavaScript.
_method hidden field workaround
The following simple technique is used by a few web frameworks:
add a hidden _method parameter to any form that is not GET or POST:
<input type="hidden" name="_method" value="PUT">
This can be done automatically in frameworks through the HTML creation helper method.
fix the actual form method to POST (<form method="post")
processes _method on the server and do exactly as if that method had been sent instead of the actual POST
You can achieve this in:
Rails: form_tag
Laravel: #method("PATCH")
Rationale / history of why it is not possible in pure HTML: https://softwareengineering.stackexchange.com/questions/114156/why-there-are-no-put-and-delete-methods-in-html-forms
for people using laravel
<form method="post" ...>
#csrf
#method('put')
...
</form>
Unfortunately, modern browsers do not provide native support for HTTP PUT requests. To work around this limitation, ensure your HTML form’s method attribute is “post”, then add a method override parameter to your HTML form like this:
<input type="hidden" name="_METHOD" value="PUT"/>
To test your requests you can use "Postman" a google chrome extension
To set methods PUT and DELETE I perform as following:
<form
method="PUT"
action="domain/route/param?query=value"
>
<input type="hidden" name="delete_id" value="1" />
<input type="hidden" name="put_id" value="1" />
<input type="text" name="put_name" value="content_or_not" />
<div>
<button name="update_data">Save changes</button>
<button name="remove_data">Remove</button>
</div>
</form>
<hr>
<form
method="DELETE"
action="domain/route/param?query=value"
>
<input type="hidden" name="delete_id" value="1" />
<input type="text" name="delete_name" value="content_or_not" />
<button name="delete_data">Remove item</button>
</form>
Then JS acts to perform the desired methods:
<script>
var putMethod = ( event ) => {
// Prevent redirection of Form Click
event.preventDefault();
var target = event.target;
while ( target.tagName != "FORM" ) {
target = target.parentElement;
} // While the target is not te FORM tag, it looks for the parent element
// The action attribute provides the request URL
var url = target.getAttribute( "action" );
// Collect Form Data by prefix "put_" on name attribute
var bodyForm = target.querySelectorAll( "[name^=put_]");
var body = {};
bodyForm.forEach( element => {
// I used split to separate prefix from worth name attribute
var nameArray = element.getAttribute( "name" ).split( "_" );
var name = nameArray[ nameArray.length - 1 ];
if ( element.tagName != "TEXTAREA" ) {
var value = element.getAttribute( "value" );
} else {
// if element is textarea, value attribute may return null or undefined
var value = element.innerHTML;
}
// all elements with name="put_*" has value registered in body object
body[ name ] = value;
} );
var xhr = new XMLHttpRequest();
xhr.open( "PUT", url );
xhr.setRequestHeader( "Content-Type", "application/json" );
xhr.onload = () => {
if ( xhr.status === 200 ) {
// reload() uses cache, reload( true ) force no-cache. I reload the page to make "redirects normal effect" of HTML form when submit. You can manipulate DOM instead.
location.reload( true );
} else {
console.log( xhr.status, xhr.responseText );
}
}
xhr.send( body );
}
var deleteMethod = ( event ) => {
event.preventDefault();
var confirm = window.confirm( "Certeza em deletar este conteúdo?" );
if ( confirm ) {
var target = event.target;
while ( target.tagName != "FORM" ) {
target = target.parentElement;
}
var url = target.getAttribute( "action" );
var xhr = new XMLHttpRequest();
xhr.open( "DELETE", url );
xhr.setRequestHeader( "Content-Type", "application/json" );
xhr.onload = () => {
if ( xhr.status === 200 ) {
location.reload( true );
console.log( xhr.responseText );
} else {
console.log( xhr.status, xhr.responseText );
}
}
xhr.send();
}
}
</script>
With these functions defined, I add a event listener to the buttons which make the form method request:
<script>
document.querySelectorAll( "[name=update_data], [name=delete_data]" ).forEach( element => {
var button = element;
var form = element;
while ( form.tagName != "FORM" ) {
form = form.parentElement;
}
var method = form.getAttribute( "method" );
if ( method == "PUT" ) {
button.addEventListener( "click", putMethod );
}
if ( method == "DELETE" ) {
button.addEventListener( "click", deleteMethod );
}
} );
</script>
And for the remove button on the PUT form:
<script>
document.querySelectorAll( "[name=remove_data]" ).forEach( element => {
var button = element;
button.addEventListener( "click", deleteMethod );
</script>
_ - - - - - - - - - - -
This article https://blog.garstasio.com/you-dont-need-jquery/ajax/ helps me a lot!
Beyond this, you can set postMethod function and getMethod to handle POST and GET submit methods as you like instead browser default behavior. You can do whatever you want instead use location.reload(), like show message of successful changes or successful deletion.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
JSFiddle: https://jsfiddle.net/enriquerene/d6jvw52t/53/
If you are using nodejs, you can install the package method-override that lets you do this using a middleware.
Link to documentation: http://expressjs.com/en/resources/middleware/method-override.html
After installing this, all I had to do was the following:
var methodOverride = require('method-override')
app.use(methodOverride('_method'))
I wrote an npm package called 'html-form-enhancer'. By dropping it into your HTML source, it takes over submission of forms with methods aside from GET and POST, and also adds application/json serialization.
<script type=module" src="html-form-enhancer.js"></script>
<form method="PUT">
...
</form>
In simple words - No.
I have tried to fire a put request in the HTML form, but it sends the POST request to the server. To add the PUT request -
We can do it by listening to the submit action in the script, then fire the put request to a particular endpoint.
Screenshot from the http-server env. test