calling laravel route in javascript - validation

Can you call a laravel route in javascript?
I am trying to implement a front-end validation with jquery validate plugin. The reason that I am doing a front-end validation instead of the validation function provided by laravel is that I am using a bootstrap modal for my login form and I do not want the user to dismiss the form upon clicking the "submit" button.
Currently I am doing something like this:
$("#modal-form-login").validate({
errorClass: "error",
errorPlacement: function(error, element) {
error.insertAfter(element.parent("div"));
},
rules: {
email: {
required: true,
email: true
},
password: {
required: true,
minlength: 4
}
},
messages: {
email: {
required: "メールアドレスが必要です",
email: "有効なメールアドレスを入力してください"
},
password: {
required: "パスワードが必要です",
minlength: jQuery.format("少なくとも {0} 文字")
}
},
submitHandler: function(form) {
$.ajax("http://mywebsite.com/login",{
dataType: 'json',
data: $('#modal-form-login').serialize(),
success: function(response) {
console.log("ok!");
}
});
}
});
I understand that the post-validation handling should be in submithandler, and I want to call my doLogin route (which is reachable via {{ URL: to("doLogin") }} in blade), but can I achieve this in javascript?

You don't want to be making php calls in your javascript. For that to work, your javascript file would have to be served by php. Your JS and CSS files should be static and should not be served by php. So the question you should be asking is "How do I inject values into javascript?" I like to pull urls out of the dom.
I'd set my login form to look something like this:
<form id="modal-form-login" method="post" action="{{ URL::to("doLogin") }}">
Then I'd update my submit handler to look like this:
submitHandler: function(form) {
$.ajax($('#modal-form-login').attr('action'), {
dataType: 'json',
data: $('#modal-form-login').serialize(),
success: function(response) {
console.log("ok!");
}
});
}
As you can see here, I'm pulling the url from the action of the form.

There are a few packages that exist for using Laravel named routes in JS.
I personally maintain Ziggy and I've also heard good things about Laroute

Related

DataTables Editor In MVC

I want to use DataTables Editor but I want full control over the post back rather than letting Editor-Server handle it. Is there a way to do this? I am able to specifiy the url in Ajax on the client side and it does post back to the Controller, the only problem is I cannot figure how to get the data out of the call.
This is the Ajax portion:
$(document).ready(function () {
editor = new $.fn.dataTable.Editor({
ajax: ({
url: "/../AnyController/Update",
dataType: "json",
contentType: "application/json",
type: 'POST'
}),
formOptions: {
inline: {
onBlur: true,
submit: 'all'
}
},
table: "#timetracker",
fields: [
{
label: "Date1:",
name: "Date1"
},
{
label: "Comment 1:",
name: "Comment1",
type: "textarea"
}
]
});
And this is the Contoller method:
[HttpPost]
public JsonResult Update(EditorReturnData wtd)
{
return Json(wtd);
}
I have tried using a variety of other method signatures but the value of wtd is always null. I have no problem loading the table just by passing Json data, but how to takeover the update process from datatables editor is eluding me.
I have one update. I could not figure out how the Get, Post and Put could all use the same Controller Method and the method takes no parameters, even for the Post and Put. Finally I figured out that Editor is passing the data in the Header and it could be accessed with Request.Body. From there it must be the Datatables dll that is doing the actual updates.
enter code hereI have found the best way to do this is to post back from ajax to a different Controller for Post and Put and you can get access to the return data from the HttpRequest body in the following manner.
public ActionResult Rest(HttpRequest request)
{
var stream = request.Body;
string url = new StreamReader(stream).ReadToEnd();
string newUrl;
while ((newUrl = Uri.UnescapeDataString(url)) != url)
url = newUrl;
I added this code to the RestController from the Datatables Dot Net Core Demo Rest example which can be downloaded from https://editor.datatables.net/
The Ajax looks like this
editor = new $.fn.dataTable.Editor( {
ajax: {
create: {
type: 'POST',
url: '/api/rest/create'
},
edit: {
type: 'PUT',
url: '/api/rest/edit'
},
remove: {
type: 'DELETE',
url: '/api/rest/remove'
}
},

PATCH AJAX Request in Laravel

Is it possible to make AJAX PATCH requests to laravel, or am I restricted to POST? Laravel uses PATCH in input hidden fields, however, I am not using form elements—just buttons that should partially update a record when clicked (via an AJAX request).
How would the route look like for this?
Routes file
Route::patch('questions/{id}', 'QuestionController#update')->before('admin');
I am not sure if laravel routes support PATCH.
Controller
public function update($id) {
if (Request::ajax() && Request::isMethod('patch')) {
//partially update record here
}
}
JS
$('div#question_preview <some button selector>').click(function (event) {
$.ajax({
url: 'questions/'+question_id,
type: 'PATCH',
data: {status: 'some status'}
});
});
I am just looking for clarity, thanks!
Yeah, it's possible try
In Your JavaScript
$('#div#question_preview <some button selector>').click(function() {
$.ajax({
url: 'questions/'+question_id,
type: 'PATCH',
data: {status: <SOME VALUE I WANT>, _method: "PATCH"},
success: function(res) {
}
});
});
In Your Route
Route::patch('questions/{id}', 'QuestionController#update')->before('admin');
In your QuestionController Controller's update method
dd(Request::method());
You will see the respond like
string(5) "PATCH"
Read more about Request Information on Laravel doc.
It's possible!
You should need to provide an extra parameter in the form request called as _method with a value PATCH.
JS
$('div#question_preview <some button selector>').click(function (event) {
$.ajax({
url: 'questions/'+question_id,
type: 'PATCH',
data: {status: 'some status',_method: 'PATCH'}
});
});
You can provide a hidden input in the view file with the value PATCH for better readability
HTML
<input type="hidden" name="_method" value="PATCH">
If you are using FormData, you need to send the request as POST. The Laravel application will automatically get it as a PATCH request because you included #method('PATCH'). So your route and method for that will get triggered.
JS with FormData
$('div#question_preview <some button selector>').click(function (event) {
let form_data= new FormData();
form_data.append('status','some status');
form_data.append('_method','PATCH');
$.ajax({
url: 'questions/'+question_id,
type: 'POST',
data: form_data
});
});

.ajaxform not working inside the validation submitHandler?

i use the jquery validation plugin to validate form before submit
in submitHandler i use ajax request to post the form with ajax
before i used .ajax to send the request but now the form have image and its so hard to
serialize the file element through the normal ajax request and because of this i used this plugin
http://www.malsup.com/jquery/form/
now after using the plugin the ajax request not working at it all don't know why
this the first example with the normal ajax call
$(document).ready(function(){
$("#categoryForm").validate({
submitHandler: function() {
$.ajax({
type:'POST',
url: 'actions/add-category.php',
data: $("#categoryForm").serialize(),
success: function(response) {
$('#status').html(response);
}
});
return false;
}
});
});
and this one after using the plugin
$(document).ready(function(){
$("#categoryForm").validate({
submitHandler: function() {
$('#categoryForm').ajaxForm(function() {
alert('the form was successfully processed');
});
return false;
}
});
});
second one is not working
Try to invert the functions:
jQuery('#form_id').ajaxForm({
beforeSubmit: function() {
jQuery("#form_id").validate({
rules: {
first_name: "required",
last_name: "required"
},
messages: {
first_name: "Required",
last_name: "Required"
}
});
return jQuery('#form_id').valid();
},
success: function(resp) {
jQuery('#resp').html(resp).fadeIn('fast');
}
});
Where #resp is the ID that will receive the HTML generated from the file your #form_id posted

Orchard CMS Ajax Anti-Forgery Token When Logged In

I am building an Orchard CMS module that I am testing on an Orchard 1.3.10 site. The module displays a details view for one of my entities and I have a "favorites" button that I would like to click and do an ajax post to a controller action to save the entity as a favorite in the database.
On the view I have the following code:
<div style="padding: 10px;">
<span data-id="#Model.Id" id="addFavorite" style="cursor: pointer;">
[Add Favorite]
</span>
</div>
<script type="text/javascript">
$("#addFavorite").click(function () {
alert("here we go...");
$.ajax({
type: "post",
dataType: "",
url: "/orchardlocal/mymodule/stuff/AddFavorite",
data: { id: $(this).data("id") },
success: function (response) {
alert("it worked");
}
});
});
</script>
My controller action is...
[HttpPost]
public ActionResult AddFavorite(int id)
{
return View();
}
When I run the site without being logged into Orchard, this code posts back just fine. If I log in and click on Add Favorite, I get this exception...
A required anti-forgery token was not supplied or was invalid.
System.Web.Mvc.HttpAntiForgeryException was unhandled by user code
Message=A required anti-forgery token was not supplied or was invalid.
Source=System.Web.WebPages
ErrorCode=-2147467259
WebEventCode=0
StackTrace:
at System.Web.Helpers.AntiForgeryWorker.Validate(HttpContextBase context, String salt)
at System.Web.Helpers.AntiForgery.Validate(HttpContextBase httpContext, String salt)
at System.Web.Mvc.ValidateAntiForgeryTokenAttribute.OnAuthorization(AuthorizationContext > filterContext)
at Orchard.Mvc.AntiForgery.AntiForgeryAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext) in C:\Code\OrchardDev2\src\Orchard\Mvc\AntiForgery\AntiForgeryAuthorizationFilter.cs:line 37
at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
InnerException:
Why does it treat the post differently when logged in and not?
How can I supply an anti-forger token to avoid this?
Thanks,
Brian
ASP.NET MVC doesn't support the generation of raw anti-forgery tokens by default. Fortunately Orchard provides an extension method for that.
You can simply change your ajax call as is:
$.ajax({
type: "post",
dataType: "",
url: "/orchardlocal/mymodule/stuff/AddFavorite",
data: {
id: $(this).data("id") },
__RequestVerificationToken: '#Html.AntiForgeryTokenValueOrchard()'
},
success: function (response) {
alert("it worked");
}
});
This technique is useful as you don't need an existing FORM on your page. Though this solution is only valid if the javascript is rendered from a Razor view.
There is still a solution if you have a separate script file from your view, which is to save the anti-forgery token inside a javascript variable declared from the view, then use it from the script:
#using(Script.Head()) {
<script type="text/javascript">
//<![CDATA[
var antiForgeryToken = '#Html.AntiForgeryTokenValueOrchard()';
//]]>
</script>
}
Then from the script:
data: {
id: $(this).data("id") },
__RequestVerificationToken: antiForgeryToken
}
If not, then the solution proposed by Darin would be he correct approach.
How can I supply an anti-forger token to avoid this?
This will depend on where the hidden field containing the anti forgery token is located on the page. For example:
$("#addFavorite").click(function () {
var token = $(':input[name="__RequestVerificationToken"]').val();
$.ajax({
type: "post",
dataType: "",
url: "/orchardlocal/mymodule/stuff/AddFavorite",
data: {
__RequestVerificationToken: token,
id: $(this).data("id")
},
success: function (response) {
alert("it worked");
}
});
});

jquery validation - waiting for remote check to complete

When I call $("form").valid() I have a remote validation check hooked up (which all works well) however if all other fields are valid the form passes validation because the remote check hasn't return a response "quick enough".
Is there a way to either force jquery validation to wait for any remote checks to be completed or hook into the complete event of the remote check call?
I am currently using the remote validator built into the jQuery validation framework http://docs.jquery.com/Plugins/Validation/Methods/remote
one way is to introduce a variable that will be set to true when the remote call comes back
var remote_complete = false;
$.ajax({
url: "test.html",
success: function(){
remote_complete = true;
}
});
while (remote_complete == false)
{
// loop until remote_complete = true;
}
Another way is to validate your form after remote validation completes
$.ajax({
url: "test.html",
success: function(){
validate_form();
}
});
you can add a custom rule and in that custom rule you can make the ajax call.
Please check the SO post here for creating custom rules.
In that function make the ajax call.
Well, if you've setup all your rules correctly, then this shouldn't be a problem. See this demo where email is being validated remotely and the validation doesn't pass until the check comes back.
Can you post a jsfiddle that highlights your problem?
http://gloryplus.com/index.php?route=product/product&path=82&product_id=173
rules: {
name: {
minlength: 2,
required: true
},
email: {
required: true,
email: true
},
subject: {
minlength: 2,
required: true
},
message: {
minlength: 2,
required: true
}
},
highlight: function(label) {
$(label).closest('.control-group').addClass('error');
},
success: function(label) {
label
.text('OK!').addClass('valid')
.closest('.control-group').addClass('success');
}

Resources