Parsley.js Dont use remote validation, if value is empty - javascript

I've got the following problem. Here is the input I want to validate
<input type="text" name="vatid" data-parsley-remote data-parsley-remote-validator='vatid'/>
and this is the asyncValidator
$('[name="vatid"]').parsley()
.addAsyncValidator('vatid', function (xhr) {
return 404 === xhr.status;
}, confighandler.getConfig().apiUrl + '/checkvatids');
My problem is, that also if the user doesn't enter a value parsley sends an request (on form submit) to the api and then the errors-mesage are triggered. How can I avoid this and only validate if the user has entered something?
Update
big thanks to milz, I've got the following solution and it works like charm :)
define([
'jquery',
'confighandler',
'requirejs-i18n!nls/labels',
'parsleyjs'
], function($, confighandler, Labels) {
'use strict';
return {
initialize: function() {
// add custom validators
window.ParsleyValidator
.addValidator('vatid', function(val) {
var isvalid;
$.ajax({
url: confighandler.getConfig().apiUrl + '/checkvatids/' + val,
dataType: 'json',
type: 'get',
async: false,
success: function(response) {
isvalid = (response.result.data.isvalid === 'true') ? true : false;
},
error: function() {
isvalid = false;
}
});
return isvalid;
}, 32).addMessage('de', 'vatid', Labels.validation.vatid);
}
};
});

You can accomplish that, but you can't use ParsleyRemote. The problem with remote validators is that you cannot verify if the value is empty or not before the remote ajax call is made.
A possible solution to this issue is adding a custom validator with .addValidator and then place an ajax call.
In this case you don't even need to check if the input has any content because the validator is only executed when the input is not empty.
<input type="text" name="vatid" data-parsley-vatid />
<script>
$(document).ready(function() {
window.ParsleyValidator
.addValidator('vatid', function (value, requirement) {
var response = false;
$.ajax({
url: confighandler.getConfig().apiUrl + '/checkvatids',
data: {vatid: value},
dataType: 'json',
type: 'get',
async: false,
success: function(data) {
response = true;
},
error: function() {
response = false;
}
});
return response;
}, 32)
.addMessage('en', 'vatid', 'Vatid is invalid.');
});
</script>
You can also check the following question that can provide adicional information: Parsley.js Trigger Error on AJAX

Related

problem with prevent and continue submit form after ajax execution

I have form with select. If select value is equal to 2 then part of form is sendign asynch via ajax and later the rest of the form should be sending via POST function. My problem is when I click submit ajax execution is performs correctly but POST method stuck, nothing happens. It looks like be page refresh.
My code
$('form').submit(function(e) {
if($('#car_type').val() == 2)
{
e.preventDefault();
e.returnValue = false;
var type = $('#new_type').val();
var number = $('#numer').val();
var form = $(this);
$.ajax({
url: "{{ url('cars/type') }}",
method: "POST",
context: form,
data: {type: type, number: number, _token: "{{ csrf_token() }}"},
success: function (result) {
if (result.result > 0) {
} else {
$("#msg").html("Errors, try again later!");
$("#msg").fadeOut(2000);
}
},
error: function (xhr) {
console.log(xhr.responseText);
},
complete: function() {
this.off('submit');
this.submit();
}
})
}
});

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>

If user manipulates the form id what is the best practice to secure it or stop this?

If user changes the formID what should i do to make the ajax call and jquery validation success.
<form id="formID" action="">
(function ($, W, D)
{
var JQUERY4U = {};
JQUERY4U.UTIL =
{
setupFormValidation: function ()
{
$("#formID").validate({
rules: {
input:"required",
},
messages: {
input: "required",
},
submitHandler: function (form) {
var form = $('#formID')[0];
var formData = new FormData(form);
$.ajax({
type: 'post',
url: '/',
data: formData,
contentType: false,
processData: false,
success: function(data) {
if (data.response == true) {
alert('true');
} else {
alert('false');
}
}, error: function (jqXHR, exception) {
console.log(jqXHR.status);
}
});
}
});
}
}
$(D).ready(function ($) {
JQUERY4U.UTIL.setupFormValidation();
});
})(jQuery, window, document);
Just remove var form = $('#formID')[0]; in the submitHandler. The form element is already exposed as an argument
The plugin will have already initialized before an ID could be changed by user in console and probably before any userscript or browser extension also
Changing an ID does not affect events already attached to that element.
Beyond that you can't control what a user does in their browser and just need to make sure your back end is secure

.NET MVC JSON Post Call response does not hit complete or success

I am new to .NET MVC so please bear with me.
I wrote a function that gets triggered when there is a blur action on the textarea control:
function extractURLInfo(url) {
$.ajax({
url: "/Popup/Url",
type: "POST",
data: { url: url },
complete: function (data) {
alert(data);
},
success: function (data) {
alert(data);
},
async: true
})
.done(function (r) {
$("#url-extracts").html(r);
});
}
jQuery(document).ready(function ($) {
$("#input-post-url").blur(function () {
extractURLInfo(this.value);
});
});
This works fine and will hit the controller:
[HttpPost]
public ActionResult Url(string url)
{
UrlCrawler crawler = new UrlCrawler();
if (crawler.IsValidUrl(url))
{
MasterModel model = new MasterModel();
model.NewPostModel = new NewPostModel();
return PartialView("~/Views/Shared/Partials/_ModalURLPartial.cshtml", model);
}
else
{
return Json(new { valid = false, message = "This URL is not valid." }, JsonRequestBehavior.AllowGet);
}
}
I get the intended results if the URL is valid; it will return a partialview to the .done() function and I just display it in code. However, if the URL is not valid i want it to hit either complete, success, or done (I have been playing around to see which it will hit but no luck!) and do something with the returned data. I had it at some point trigger either complete or success but the data was 'undefined'. Can someone help me out on this?
Thanks!
In both cases your controller action is returning 200 status code, so it's gonna hit your success callback:
$.ajax({
url: "/Popup/Url",
type: "POST",
data: { url: url },
success: function (data) {
if (data.message) {
// Your controller action return a JSON result with an error message
// => display that message to the user
alert(data.message);
} else {
// Your controller action returned a text/html partial view
// => inject this partial to the desired portion of your DOM
$('#url-extracts').html(data);
}
}
});
But of course a much better and semantically correct approach is to set the proper status code when errors occur instead of just returning some 200 status code:
[HttpPost]
public ActionResult Url(string url)
{
UrlCrawler crawler = new UrlCrawler();
if (crawler.IsValidUrl(url))
{
MasterModel model = new MasterModel();
model.NewPostModel = new NewPostModel();
return PartialView("~/Views/Shared/Partials/_ModalURLPartial.cshtml", model);
}
else
{
Response.StatusCode = 400;
Response.TrySkipIisCustomErrors = true;
return Json(new { valid = false, message = "This URL is not valid." }, JsonRequestBehavior.AllowGet);
}
}
and then in your AJAX call you would handle those cases appropriately:
$.ajax({
url: "/Popup/Url",
type: "POST",
data: { url: url },
success: function (data) {
$('#url-extracts').html(data);
},
error: function(xhr) {
if (xhr.status == 400) {
// The server returned Bad Request status code
// => we could parse the JSON result
var data = JSON.parse(xhr.responseText);
// and display the error message to the user
alert(data.message);
}
}
});
Also don't forget that you have some standard way of returning your error messages you could subscribe to a global .ajaxError() handler in jQuery instead of placing this code in all your AJAX requests.

MVC3 AJAX passing data to controller. It's being submitted twice

So I have a table that gets transformed to an array using:
var result = $("#enrolledStudents").sortable('toArray');
But when I go a head an pass that into my controller like so:
$("#update-enroll").click(function () {
var result = $("#enrolledStudents").sortable('toArray');
$.ajax({
url: '#Url.Action("Enrollment", "Classroom")',
data: { students: result },
type: 'POST',
traditional: true
});
});
My debugging breakpoint gets set off twice, causing issues to arise. What is the proper way to submit data to my controller on POST?
Per my comments, there are a couple things that could be causing this.
You have have the unobtrusive file(s) loaded multiple times
Your form has an action method defined, and your button is inside the form tag as a submit button. This will submit the form, and then the click will also submit the form - see example
Example
<form action="/somerowout/someaction">
<input type="text" id="text1"/>
<input type="text" id="text1"/>
<input type="submit" />
</form>
If you need to validate a value on your form before posting, don't hook up an additional Ajax call. Your javascript will look something like:
$(document).ready(function () {
$("form").submit(function(){
var result = $("#enrolledStudents").sortable('toArray');
if(result == null){
//do something to show validation failed
return false;
}
return true;
});
});
And your form code would then look something like:
#using (#Ajax.BeginForm(new AjaxOptions { })) {
<input type="text" id="text1"/>
<input type="text" id="text1"/>
<input type="submit" />
}
If you want to use Ajax rather than the Html Helpers, use a div instead of a form, and you won't get a duplicate post. Here's how you could achieve this:
<div id="enrolledStudents">
<--! your elements -->
<button id="saveStudents">Save</button>
</div>
JavaScript
$(document).ready(function () {
$("saveStudents").click(function(){
var result = $("#enrolledStudents").sortable('toArray');
if(result !== null){ /* do some kind of check here. */
$.ajax({
url: '#Url.Action("Enrollment", "Classroom")',
data: { students: result },
type: 'POST',
traditional: true,
success : function(data) {
if (data.status) {
window.location = data.route;
}
}
})
} else {
/* notify ui that save didn't happpen */
}
});
});
Example Controller Action
When posting your data using Ajax, here's an example of how to pass the route
[HttpPost]
public ActionResult SomethingPost(SomeModel model) {
if (Request.IsAjaxRequest()) {
var json = new {
status = true,
route = #Url.RouteUrl("MyRouteName", new { /* route values */ })
};
return Json(json, JsonRequestBehavior.AllowGet);
}
}
Are you sure you are preventing the default behaviour (form POSTING) of the submit button ? use preventDefault to do so.
$("#update-enroll").click(function (e) {
e.preventDefault();
//rest of the code
});
EDIT : As per the comment
To do the redirect in the ajax handler, you need to return the URL to be redirected in a JSON Response back to the calle.
[HttpPost]
public ActionResult Classroom(string students)
{
//do some operaton
if(Request.IsAjax())
{
//This is an Ajax call
return Json(new
{
Status="Success",
NewUrl = Url.Action("Index","Home")
});
}
else
{
//Normal request. Use RedirectToActiom
return RedirectToAction("Index","Home");
}
}
Now in your ajax call check the JSON result and do the redirect.
$.ajax({
url: '#Url.Action("Enrollment", "Classroom")',
data: { students: result },
type: 'POST',
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
if(data.Status=="Success")
{
window.location.href = data.Newrl;
}
else
{
alert("some error");
}
}
});
Check if you don't have the jquery files loaded twice. I had this behavior and the problem was files loaded twice.

Categories

Resources