How to process dynamic added html form on NodeJS express - javascript

My JQuery code appends html form to the DOM like this.
$("#form-container").empty().append("<form method='POST' action='/process-form' id='my-form'>
<input name='myfield'>
<button type='submit'>Submit</button>
</form>")
And my server side code looks like this
//I have app.use(bodyParser.urlencoded({extended: true}) middleware
router.post('/process-form',function(req,res){
console.log(req.body)
})
The console.log returns an empty object. However, when I create a new page with just the form and submit the form, it returns the form values as expected. Any help why it behaves like that?
EDIT:
JQuery code for AJAX request
$(document).on('submit', '#my-form', function(evt) {
evt.preventDefault();
let url = $(this).attr('action')
let method = $(this).attr('post')
$.ajax({
url,
type: 'POST',
success: function(data) {
console.log(data)
},
error: function(err) {
console.log(err)
}
})
})

You aren't sending any data with our Ajax post. You have to get the data from the form and send it yourself for an Ajax call.
There are numerous ways to get the data out of the form and package it up for jQuery. One way which puts it in the URLencoded form is to get the DOM element for the form and execute const formData = form.serialize() and then send that in the data property for $.ajax().
You could put that together like this:
$(document).on('submit', '#my-form', function(evt) {
evt.preventDefault();
let url = $(this).attr('action')
let method = $(this).attr('post')
$.ajax({
url,
type: 'POST',
data: $(this).serialize(),
success: function(data) {
console.log(data)
},
error: function(err) {
console.log(err)
}
})
});

Related

emailJS POST https://api.emailjs.com/api/v1.0/email/send 400 reactjs

I have this problem 400. I use Emailjs i put the good id but form
doesn't send. I don't understand why.I think is the problem with emailjs.min.js
error
index.html
email
Thank you for yours answers
I looked at your index.html and I only see where you passed in your user ID. Can you post the part where you have to pull the form data from the html inputs and append them to a new Form object? This is more or less the main side of the code, I used jQuery to handle it. Example.
$('#contact-form').on('submit', function(event) {
event.preventDefault(); // prevent reload
let formData = new FormData(this);
formData.append('service_id', 'default_service');
formData.append('template_id', 'template_mezfpy6');
formData.append('user_id', 'user_ID');
$.ajax('https://api.emailjs.com/api/v1.0/email/send-form', {
type: 'POST',
data: formData,
contentType: false, // auto-detection
processData: false // no need to parse formData to string
}).done(function() {
console.log('Your mail is sent!');
}).fail(function(error) {
alert('Oops... ' + JSON.stringify(error));
});
});

How to run JavaScript code on Success of Form submit?

I have an Asp.Net MVC web application. I want to run some code on the successful response of the API method which is called on form submit.
I have the below Code.
#using (Html.BeginForm("APIMethod", "Configuration", FormMethod.Post, new { #class = "form-horizontal", id = "formID" }))
{
}
$('#formID').submit(function (e) {
$.validator.unobtrusive.parse("form");
e.preventDefault();
if ($(this).valid()) {
FunctionToBeCalled(); //JS function
}
}
But FunctionToBeCalled() function gets called before the APIMethod(), but I want to run the FunctionToBeCalled() function after the response of APIMethod().
So I made the below changes by referring this link. But now the APIMethod is getting called twice.
$('#formID').submit(function (e) {
$.validator.unobtrusive.parse("form");
e.preventDefault();
if ($(this).valid()) {
//Some custom javasctipt valiadations
$.ajax({
url: $('#formID').attr('action'),
type: 'POST',
data: $('#formID').serialize(),
success: function () {
console.log('form submitted.');
FunctionToBeCalled(); //JS function
}
});
}
}
function FunctionToBeCalled(){alert('hello');}
So I am not able to solve the issue.
If you want to execute some work on success, fail, etc. situation of form submission, then you would need to use Ajax call in your view. As you use ASP.NET MVC, you can try the following approach.
View:
$('form').submit(function (event) {
event.preventDefault();
var formdata = $('#demoForm').serialize();
//If you are uploading files, then you need to use "FormData" instead of "serialize()" method.
//var formdata = new FormData($('#demoForm').get(0));
$.ajax({
type: "POST",
url: "/DemoController/Save",
cache: false,
dataType: "json",
data: formdata,
/* If you are uploading files, then processData and contentType must be set to
false in order for FormData to work (otherwise comment out both of them) */
processData: false, //For posting uploaded files
contentType: false, //For posting uploaded files
//
//Callback Functions (for more information http://api.jquery.com/jquery.ajax/)
beforeSend: function () {
//e.g. show "Loading" indicator
},
error: function (response) {
$("#error_message").html(data);
},
success: function (data, textStatus, XMLHttpRequest) {
$('#result').html(data); //e.g. display message in a div
},
complete: function () {
//e.g. hide "Loading" indicator
},
});
});
Controller:
public JsonResult Save(DemoViewModel model)
{
//...code omitted for brevity
return Json(new { success = true, data = model, message = "Data saved successfully."
}
Update: If SubmitButton calls a JavaScript method or uses AJAX call, the validation should be made in this method instead of button click as shown below. Otherwise, the request is still sent to the Controller without validation.
function save(event) {
//Validate the form before sending the request to the Controller
if (!$("#formID").valid()) {
return false;
}
...
}
Update your function as follows.
$('#formID').submit(function (e) {
e.preventDefault();
try{
$.validator.unobtrusive.parse("form");
if ($(this).valid()) {
$.ajax({
url: $('#formID').attr('action'),
type: 'POST',
data: $('#formID').serialize(),
success: function () {
console.log('form submitted.');
FunctionToBeCalled(); //JS function
}
});
}
}
catch(e){
console.log(e);
}
});
Check the browser console for fetching error. The above code will prevent of submitting the form.
I think line $.validator.unobtrusive.parse("form") were throwing error.
For that use you need to add the following jQuery libraries.
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>
I think you should remove razor form tag if you want to post your form using ajax call and add post api URL directly to ajax request instead of getting it from your razor form tag using id:
Here is the revised version of your code :
<form method="post" id="formID">
<!-- Your form fields here -->
<button id="submit">Submit</button>
</form>
Submit your form on button click like:
$('#submit').on('click', function (evt) {
evt.preventDefault();
$.ajax({
url: "/Configuration/APIMethod",
type: 'POST',
dataType : 'json',
data: $('#formID').serialize(),
success: function () {
console.log('form submitted.');
FunctionToBeCalled(); //JS function
}
});
});
function FunctionToBeCalled(){alert('hello');}
You need to use Ajax.BeginForm, this article should help [https://www.c-sharpcorner.com/article/asp-net-mvc-5-ajax-beginform-ajaxoptions-onsuccess-onfailure/ ]
The major thing here is that I didn't use a submit button, I used a link instead and handled the rest in the js file. This way, the form would nver be submitted if the js file is not on the page, and with this js file, it initiates a form submission by itself rather than th form submitting when the submit button is clicked
You can adapt this to your solution as see how it respond. I have somthing like this in production and it works fine.
(function() {
$(function() {
var _$pageSection = $('#ProccessProductId');
var _$formname = _$pageSection.find('form[name=productForm]');
_$formname.find('.buy-product').on('click', function(e) {
e.preventDefault();
if (!_$formname.valid()) {
return;
}
var formData = _$formname.serializeFormToObject();
//set busy animation
$.ajax({
url: 'https://..../', //_$formname.attr('action')
type: 'POST',
data: formData,
success: function(content) {
AnotherProcess(content.Id)
},
error: function(e) {
//notify user of error
}
}).always(function() {
// clear busy animation
});
});
function AnotherProcess(id) {
//Perform your operation
}
}
}
<div class="row" id="ProccessProductId">
#using (Html.BeginForm("APIMethod", "Configuration", FormMethod.Post, new { #class = "form-horizontal", name="productForm" id = "formID" })) {
<li class="buy-product">Save & Proceed</li>
}
</div>

Laravel - do not continue after form validator if ajax request

I want to create a ajax form validation that verifies that form data and gives user instant feedback before really submitting the form.
For this i added a javascript function on form submit:
<form id="x" onsubmit="return dosubmit(this)" action="{{ url('/x') }}" method="POST">
<script>
function dosubmit(form) {
$.ajax({
url: $(form).attr('action'),
type: 'post',
data: $(form).serializeArray()
}).done(function (data) {
form.submit();
}).fail(function (data) {
alert('error');
});
return false;
}
</script>
And i have custom a form validator request:
class X extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required',
];
}
}
When my ajax request fails everything works fine. My form validator returns the error in json and i can display it to user. The problem is that when it is successful it actually posts the data two times - first time from the ajax request and second time because i call form.submit() after ajax request is successful. Because i want to redirect the user after submit i would actually like only the second submit to reach the controller. This means i have to stop the ajax request after validation. My current workaround is that i have a line like this in my controller:
public function store(X $request)
{
if ($request->ajax()) {
return;
}
// only actual request reaches here
}
This works, but its not pretty. I don't like including this line in my controller. I would be happy if i could do something similar in my request validator, but I cant find a good way to return after validation from there. Any ideas how can i accomplish this?
You can try it like this:
<script>
function dosubmit(form) {
$.ajax({
async: false, // make ajax not async
url: $(form).attr('action'),
type: 'post',
data: $(form).serializeArray()
}).done(function (data) {
form.submit();
}).fail(function (data) {
alert('error');
});
return false;
}
</script>
and in controller just do it normally without this...
if ($request->ajax()) {
return;
}
And please give feedback if it works...I am also interested.
Your problem can be solved with some changed in javascript code. I think you're confused about what deferred.done() method will do. In your code, you're submitting your form twice.
Let me break down your js script, the done() method is used to do further actions after submitting your form (Please refer).
In your code, the first $.ajax actually submits your form to backend (here, if there are any errors from backend you can handle them in fail section). If the form submits successfully without any errors, then in done section you can define functions or actions about what you want to do after a successful form submission.
Instead of defining what to do after a successful form submission, you are resubmitting the same form again. So remove that part from js code and also the workaround you've done in your backend.
function dosubmit(form) {
$.ajax({
url: $(form).attr('action'),
type: 'post',
data: $(form).serializeArray()
}).done(function (data) {
// form.submit();
// handle successful form submission
}).fail(function (data) {
alert('error');
});
return false;
}

JQuery ajaxSetup - appending global data to FormData

I am passing a global parameter in all jquery ajax requests using the ajaxSetup function like below
$.ajaxSetup({
data: {
csrf: csrfValue
}
});
This works fine for all requests except when I do a ajax file upload
var formData = new FormData();
formData.append('attachedFile', file);
$.ajax({
url: '/fileUpload',
data: formData,
success: function() {
....
}
});
Since I am using a FormData, the csrf param is not getting appended. Is there a proper way to append common data to all types of ajax requests?
You can fix this by using $.extend and $.ajaxPrefilter to merge the default data with the data you've provided:
UPDATED:
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
if (originalOptions.data instanceof FormData) {
originalOptions.data.append(csrfParamName, csrfParamValue);
}
});
Yes it does not work because you are using FormData.
Add the csrfValue to your ajax data or
add a hidden field inside your form
<input type="hidden" value="{{ csrfValue }}"?>

File Upload without Form

Without using any forms whatsoever, can I just send a file/files from <input type="file"> to 'upload.php' using POST method using jQuery. The input tag is not inside any form tag. It stands individually. So I don't want to use jQuery plugins like 'ajaxForm' or 'ajaxSubmit'.
You can use FormData to submit your data by a POST request. Here is a simple example:
var myFormData = new FormData();
myFormData.append('pictureFile', pictureInput.files[0]);
$.ajax({
url: 'upload.php',
type: 'POST',
processData: false, // important
contentType: false, // important
dataType : 'json',
data: myFormData
});
You don't have to use a form to make an ajax request, as long as you know your request setting (like url, method and parameters data).
All answers here are still using the FormData API. It is like a "multipart/form-data" upload without a form. You can also upload the file directly as content inside the body of the POST request using xmlHttpRequest like this:
var xmlHttpRequest = new XMLHttpRequest();
var file = ...file handle...
var fileName = ...file name...
var target = ...target...
var mimeType = ...mime type...
xmlHttpRequest.open('POST', target, true);
xmlHttpRequest.setRequestHeader('Content-Type', mimeType);
xmlHttpRequest.setRequestHeader('Content-Disposition', 'attachment; filename="' + fileName + '"');
xmlHttpRequest.send(file);
Content-Type and Content-Disposition headers are used for explaining what we are sending (mime-type and file name).
I posted similar answer also here.
UPDATE (January 2023):
You can also use the Fetch API to upload a file directly as binary content (as also was suggested in the comments).
const file = ...file handle...
const fileName = ...file name...
const target = ...target...
const mimeType = ...mime type...
const promise = fetch(target, {
method: 'POST',
body: file,
headers: {
'Content-Type': mimeType,
'Content-Disposition', `attachment; filename="${fileName}"`,
},
},
});
promise.then(
(response) => { /*...do something with response*/ },
(error) => { /*...handle error*/ },
);
See also a related question here: https://stackoverflow.com/a/48568899/1697459
Step 1: Create HTML Page where to place the HTML Code.
Step 2: In the HTML Code Page Bottom(footer)Create Javascript: and put Jquery Code in Script tag.
Step 3: Create PHP File and php code copy past. after Jquery Code in $.ajax Code url apply which one on your php file name.
JS
//$(document).on("change", "#avatar", function() { // If you want to upload without a submit button
$(document).on("click", "#upload", function() {
var file_data = $("#avatar").prop("files")[0]; // Getting the properties of file from file field
var form_data = new FormData(); // Creating object of FormData class
form_data.append("file", file_data) // Appending parameter named file with properties of file_field to form_data
form_data.append("user_id", 123) // Adding extra parameters to form_data
$.ajax({
url: "/upload_avatar", // Upload Script
dataType: 'script',
cache: false,
contentType: false,
processData: false,
data: form_data, // Setting the data attribute of ajax with file_data
type: 'post',
success: function(data) {
// Do something after Ajax completes
}
});
});
HTML
<input id="avatar" type="file" name="avatar" />
<button id="upload" value="Upload" />
Php
print_r($_FILES);
print_r($_POST);
Basing on this tutorial, here a very basic way to do that:
$('your_trigger_element_selector').on('click', function(){
var data = new FormData();
data.append('input_file_name', $('your_file_input_selector').prop('files')[0]);
// append other variables to data if you want: data.append('field_name_x', field_value_x);
$.ajax({
type: 'POST',
processData: false, // important
contentType: false, // important
data: data,
url: your_ajax_path,
dataType : 'json',
// in PHP you can call and process file in the same way as if it was submitted from a form:
// $_FILES['input_file_name']
success: function(jsonData){
...
}
...
});
});
Don't forget to add proper error handling
Try this puglin simpleUpload, no need form
Html:
<input type="file" name="arquivo" id="simpleUpload" multiple >
<button type="button" id="enviar">Enviar</button>
Javascript:
$('#simpleUpload').simpleUpload({
url: 'upload.php',
trigger: '#enviar',
success: function(data){
alert('Envio com sucesso');
}
});
A non-jquery (React) version:
JS:
function fileInputUpload(e){
let formData = new FormData();
formData.append(e.target.name, e.target.files[0]);
let response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
let result = await response.json();
console.log(result.message);
}
HTML/JSX:
<input type='file' name='fileInput' onChange={(e) => this.fileInput(e)} />
You might not want to use onChange, but you can attach the uploading part to any another function.
Sorry for being that guy but AngularJS offers a simple and elegant solution.
Here is the code I use:
ngApp.controller('ngController', ['$upload',
function($upload) {
$scope.Upload = function($files, index) {
for (var i = 0; i < $files.length; i++) {
var file = $files[i];
$scope.upload = $upload.upload({
file: file,
url: '/File/Upload',
data: {
id: 1 //some data you want to send along with the file,
name: 'ABC' //some data you want to send along with the file,
},
}).progress(function(evt) {
}).success(function(data, status, headers, config) {
alert('Upload done');
}
})
.error(function(message) {
alert('Upload failed');
});
}
};
}]);
.Hidden {
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-controller="ngController">
<input type="button" value="Browse" onclick="$(this).next().click();" />
<input type="file" ng-file-select="Upload($files, 1)" class="Hidden" />
</div>
On the server side I have an MVC controller with an action the saves the files uploaded found in the Request.Files collection and returning a JsonResult.
If you use AngularJS try this out, if you don't... sorry mate :-)

Categories

Resources