Laravel 9, the ajax didnt catch the data from controller - laravel-9

I'm trying to pass the error messages to the view using messages (), what I'm expected is the error will pop up at top of the form
The Controller
if ($validator->fails()) {
# code...
return response()->json([
'status' => 400,
'errors' => $validator->messages()
]);
}
The Script
$(document).on('submit', '#AddForm', function(e) {
e.preventDefault();
let formData = new formData($('#AddForm')[0]);
$.ajax({
type: "POST",
url: "/menu",
data: FormData,
contentType: false,
processData: false,
success: function(response) {
if (response.status == 400) {
$('#save_errorList').html("");
$('#save_errorList').removeClass('d-none');
$.each(response.errors, function(key, err_value) {
$('#save_errorList').append('<li>' + err_value +
'</li>');
});
}
}
});
});
View
<form id="addForm" method="POST" enctype="multipart/form-data">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="modal-body">
<ul class="alert alert-warning d-none" id="save_errorList"></ul>
This the messages which is true I'm trying to pass the errors while the input in empty condition:
but I want the error show at my view, did I miss something ?

Related

How to send upload file to controller - files is always empty

UserAdmin.cshtml
<div class="modal-body">
<form id="upload-file-dialog-form"
class="needs-validation form-group" novalidate
onsubmit="UploadFile()"
enctype="multipart/form-data"
method="post">
<div class="col-md-10">
<p>Upload one or more files using this form:</p>
<input type="file" name="file_Uploader" />
</div>
<div class="form-group">
<div class="col-md-10 modal-footer">
<input type="submit" class="btn btn-primary" value="Upload"/>
</div>
</div>
</form>
</div>
UserAdmin.js
function UploadFile() {
var form = $('form')[0];
var formData = new FormData(form);
console.log(formData);
$.ajax({
url: '/API/Upload',
type: 'POST',
data: formData,
contentType: false,
processData: false,
success: function (data) {
},
error: function () {
}
});
}
Controller
[HttpPost]
public async Task<IActionResult> Upload(List<IFileUpload> files)
{
try
{
var check = (HttpContext.Request.Form.Files);
long size = files.Sum(f => f.Length);
//some code removed
return Ok(new { count = files.Count, size, filePaths });
}
catch (Exception exc)
{
logger.Error("Error in upload() " + exc.Message);
throw;
}
}
the files in controller is always 0.
If onsubmit="UploadFile()" is replaced with
asp-controller="API" asp-action="Upload"
then I get something in check but again converting it to List of IFileUpload is another blocker
First of all, If you want to upload multiple files you have to add multiple="multiple" in your input. FormData will be empty if you print it like this, you have to iterate through the items.
<input type="file" name="file_Uploader" multiple="multiple" />
Please follow the codes below, I tested it working.
Complete form
<form id="upload-file-dialog-form"
onsubmit="UploadFile(event)">
<div class="col-md-10">
<p>Upload one or more files using this form:</p>
<input type="file" name="file_Uploader" multiple="multiple" />
</div>
<div class="form-group">
<div class="col-md-10 modal-footer">
<input type="submit" class="btn btn-primary" value="Upload" />
</div>
</div>
</form>
Construct form data like below
<script>
function UploadFile(e) {
e.preventDefault();
var formData = new FormData($('#upload-file-dialog-form')[0]);
$.each($("input[type='file']")[0].files, function(i, file) {
formData.append('files', file);
});
$.ajax({
url: '/API/Upload',
type: 'POST',
data: formData,
contentType: false,
processData: false,
success: function(data) {
},
error: function() {
}
});
}
</script>
Action method
[HttpPost]
public async Task<IActionResult> Upload(List<IFormFile> files)
{
try
{
var check = (HttpContext.Request.Form.Files);
long size = files.Sum(f => f.Length);
return Ok(new { count = files.Count, size });
}
catch (Exception exc)
{
_logger.LogWarning("Error in upload() " + exc.Message);
throw;
}
}
In model class, use IFormFile
public List<IFormFile> file_Uploader {get;set;}"
In controller, change the parameter like this
public async Task<IActionResult> Upload(List<IFormFile> file_Uploader)
add multiple to upload more files, and keep the name attribute the same as parameter to post value, code like below:
<input type="file" name="file_Uploader" multiple/>
result:

axios sending null when uploading files to laravel api. Error Message: "Call to a member function store() on null"

I have a form with file upload. I am using vue, axios and laravel 7 at the moment.
My form is as given below:
<form v-on:submit.prevent="createTask" enctype="multipart/form-data" method="post">
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" name="title" id="title" v-model="task.title" />
<label for="content">Content</label>
<textarea v-model="task.content" class="form-control" id="content" name="content" rows="4" ></textarea>
<button type="submit" class="btn btn-sm btn-primary
pull-right" style="margin:10px; padding:5 15 5 15; background-color:#4267b2">Save Task</button>
<span>
<button #click="removeImage" class="btn btn-sm btn-outline-danger" style="margin:10px; padding:5 15 5 15; ">Remove File</button>
</span>
<input type="file" id="image" name="image" />
</div>
</form>
Axios submission
createTask() {
console.log(document.getElementById('image').files[0])
axios({
headers: { 'Content-Type': 'multipart/form-data' },
method: 'post',
url: '/api/tasks',
data: {
task_id : this.task.id,
title : this.task.title,
content : this.task.content,
created_by : this.$userId,
image : document.getElementById('image').files[0],
}
})
.then(res => {
// check if the request is successful
this.$emit("task-created");
this.task = {}
})
.catch(function (error){
console.log(error)
});
}
My controller code
public function store(Request $request)
{
$task = $request->isMethod('put') ? Task::findOrFail($request->task_id) : New Task;
$task->id = $request->input('task_id');
$task->title = $request->input('title');
$task->content = $request->input('content');
$task->views = $request->input('views');
$task->created_by = $request->input('created_by');
$task->image = $request->image->store('images');
//$task->image = $request->file('image')->store('images');
if($task->save()) {
return new TaskResource($task);
}
}
The request payload
{task_id: "", title: "test", content: "test content", created_by: "1", image: {}}
We can see the image attribute is empty
The response error message
"Call to a member function store() on null"
The output of console.log(document.getElementById('image').files[0])
File {name: "test.jpg", lastModified: 1590920737890, lastModifiedDate: Sun May 31 2020 11:25:37 GMT+0100 (British Summer Time), webkitRelativePath: "", size: 436632, …}
lastModified: 1590920737890
lastModifiedDate: Sun May 31 2020 11:25:37 GMT+0100 (British Summer Time) {}
name: "test.jpg"
size: 436632
type: "image/jpeg"
webkitRelativePath: ""
proto: File
I solved this problem by changing the axios post request as follows. I used FormData to append and send data to server
createTask() {
let data = new FormData;
data.append('image', document.getElementById('image').files[0]);
data.append('task_id', this.task.id);
data.append('title', this.task.title);
data.append('content', this.task.content);
data.append('created_by', this.$userId);
axios({
headers: { 'Content-Type': 'multipart/form-data' },
method: 'post',
url: '/api/tasks',
data: data
})
.then(res => {
// check if the request is successful
this.$emit("task-created");
this.image = '';
this.task = {}
})
.catch(function (error){
console.log(error)
});
}
Assuming the image column has the right structure, you could try with somenthing like this:
<?php
public function store(Request $request)
{
$task = $request->isMethod('put') ? Task::findOrFail($request->task_id) : New Task;
$task->id = $request->input('task_id');
$task->title = $request->input('title');
$task->content = $request->input('content');
$task->views = $request->input('views');
$task->created_by = $request->input('created_by');
$task->image = $request->hasFile('images')
? $request->file('images')
: null;
if($task->save()) {
return new TaskResource($task);
}
}
laravel 5.4 upload image read here for more information

Submit form to Quip API with Axios

I want to submit a form data to Quip's Create Document API using vue.js and axios. This is what I've tried so far:
Form:
<form #submit="saveToQuip" method="POST" action="./post-order.html">
<div class="row">
<div class="col-lg-6 col-md-6">
<div class="row">
<div class="col-lg-12">
<div class="checkout__input">
<label>Receiver's Name<span>*</span></label>
<input type="text" name="First Name" v-model="fullname" required>
</div>
</div>
</div>
.....
</form>
JS:
new Vue({
el: '#submit-order',
data () {
return {
cartItems: [],
fullname: '',
facebookname: '',
email: 'NONE',
address: '',
phone_number: '',
payment_method: '',
delivery_dtime: '',
ordernotes: 'NONE'
}
},
methods:{
saveToQuip(submitEvent) {
......
axios.post('where-to-send-form-data', {
headers : {
Authorization: 'Bearer ' + personal_token,
'Content-Type': content_type
//Access-Control-Allow-Origin : *
},
params: {
title: this.fullname,
type: 'document',
member_ids: folder_id,
content: content
}
})
.then((response) => {
console.log(response)
})
.catch(function (error) {
console.log(error);
})
.then(function () {
}); ;
}
}
})
When I try to submit my form, it does not run the axios post command, and there is no error in the console. It just redirects the page to the next page. How do I achieve this?
Remove both method and action from your form and trigger the action from a button
<form #submit="saveToQuip" method="POST" action="./post-order.html">
to
<form>
...
<button #click="saveToQuip()">SAVE</button>

Switching Google reCaptcha Version 1 from 2

I have successfully designed and implemented Google reCaptcha Version 2 but now my Manager wants that to be of version 1 with numbers to be entered and validated. Is there a way to switch from later to former i.e.- from 2 to 1. I am using following library for reCaptcha:
<script src='https://www.google.com/recaptcha/api.js'></script>
Update..
To implement Captcha inside form i am using following HTML..
<form class="contact_form" action="#" method="post" name="contact_form">
<div class="frm_row">
<label id="lblmsg" />
<div class="clear">
</div>
</div>
<div class="g-recaptcha" data-sitekey="6Lduiw8TAAAAAOZRYAWFUHgFw9_ny5K4-Ti94cY9"></div>
<div class="login-b">
<span class="button-l">
<input type="button" id="Captcha" name="Submit" value="Submit" />
</span>
<div class="clear"> </div>
</div>
</form>
As i need to get the Captcha inside the above form to Validate and get the response on button click but as now i am using <script src="http://www.google.com/recaptcha/api/challenge?k=6Lduiw8TAAAAAOZRYAWFUHgFw9_ny5K4-Ti94cY9"></script> , so not getting the Captcha inside the form ..Please help me to get that ..Also here is the Jquery Ajax code to send the request on Server side code..
$(document).ready(function () {
alert("hii1");
$('#Captcha').click(function () {
alert("Hii2");
if ($("#g-recaptcha-response").val()) {
alert("Hii3");
var responseValue = $("#g-recaptcha-response").val();
alert(responseValue);
$.ajax({
type: 'POST',
url: 'http://localhost:64132/ValidateCaptcha',
data: JSON.stringify({ "CaptchaResponse": responseValue }),
contentType: "application/json; charset=utf-8",
dataType: 'json', // Set response datatype as JSON
success: function (data) {
console.log(data);
if (data = true) {
$("#lblmsg").text("Validation Success!!");
} else {
$("#lblmsg").text("Oops!! Validation Failed!! Please Try Again");
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Error");
}
});
}
});
});
Please help me ..Thanks..
You have to verify the reCaptcha at "http://www.google.com/recaptcha/api/verify" on Server side.
The parameters of this are:
privatekey: Your Private Key
remoteip: User's IP Address
challenge: Value of input[name=recaptcha_response_field]
response: Value of input[name=recaptcha_challenge_field]
Therefore, you have to post them on your server-side method like this:
cshtml file:
var recaptchaResponseField=$("input[name=recaptcha_response_field]").val();
var recaptchaChallengeField=$("input[name=recaptcha_challenge_field]").val();
// ajax block
$.ajax({
url: '/api/VerifyReCaptcha/', // your Server-side method
type: 'POST',
data: {
ipAddress: '#Request.ServerVariables["REMOTE_ADDR"]',
challengeField: recaptchaChallengeField,
responseField: recaptchaResponseField
},
dataType: 'text',
success: function (data) {
// Do something
},
Since you are using .NET so an example of C# code is as follows:
cs file:
using System.Net;
using System.Collections.Specialized;
[HttpPost]
public bool VerifyReCaptcha(string ipAddress, string challengeField, string responseField)
{
string result = "";
using (WebClient client = new WebClient())
{
byte[] response =
client.UploadValues("http://www.google.com/recaptcha/api/verify", new NameValueCollection()
{
{ "privatekey", "{Your private key}" },
{ "remoteip", ipAddress },
{ "challenge", challengeField },
{ "response", responseField },
});
result = System.Text.Encoding.UTF8.GetString(response);
}
return result.StartsWith("true");
}

Single file upload using Ajax, MVC 5 and jQuery

I am using asp.net MVC 5 to do a simple single file upload using the HTML element.I make an AJAX post request.The form has other fileds in addition to the file element.I tried diffrent methods available on the internet ,but nothing seems to be working.Is this really possible using the element?Using a jQuery plugin is my last option.I like to make things simple in my application
my HTML
#using (Html.BeginForm("Edit", "Person", FormMethod.Post, new { id = "form-person-edit-modal", enctype = "multipart/form-data" }))
{
<div class="row">
<div class="row">
<div class="small-4 columns">
#Html.GenericInputFor(m => m.Name, Helpers.HtmlInputType.Text, new { id = "input-name" })
</div>
<div class="small-4 columns">
#Html.GenericInputFor(m => m.Description, Helpers.HtmlInputType.TextArea, new { id = "input-description" })
</div>
<div class="small-4 columns">
<label>Choose File</label>
<input type="file" name="attachment" id="attachment" />
</div>
</div>
</div>
<div class="row">
<div class="small-12 columns">
<input type="submit" id="image-submit" value="Save"/>
</div>
</div>
}
-- C# ViewModel
public class Person
{
Public string Name{get;set;}
Public string Description{get;set;}
public HttpPostedFileBase Attachment { get; set; }
}
-- Jquery Ajax Post:
$.ajax({
url: url,
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(data),
dataType: 'json',
success: function (data, textStatus, jqXHR) {
if (data.Success) {
success(data, textStatus, jqXHR);
} else {
if (error) {
error();
}
}
},
error: function (jqXHR, textStatus, errorThrown) {
if (error)
error();
}
});
-- Javacsript where I try to get the file content,before passing that data to the above method
function getData(){
return {
Name:$('#input-name').val(),
Description:$('#input-description').val(),
Attachment:$('#form-ticket-edit-modal').get(0).files[0]
};
}
But the Attachment on the controller is null.I tried this as below,but doesnt seem to be working
[HttpPost]
public ActionResult Edit(ViewPerson person,HttpPostedFileBase attachment)
{
}
Is this still possible,or should I use a jQuery plugin(If so,which one do you recommend?)
I have used your code to show how to append image file,Please use Formdata() method to append your data and File and send through ajax.
Try Changing as per your requirement.
$("#SubmitButtonID").on("click",function(){
var mydata=new Formdata();
mydata.append("Name",$("#name").val());
mydata.append("Image",Image.files[0]);
alert(mydata);
$.ajax({
url: "#url.Action("ActionMethodName","ControllerName")",
type: 'POST',
contentType:false,
processData;false,
data: mydata,
dataType: 'json',
success: function (data, textStatus, jqXHR) {
if (data.Success) {
success(data, textStatus, jqXHR);
} else {
if (error) {
error();
}
}
},
error: function (jqXHR, textStatus, errorThrown) {
if (error)
error();
}
});
});
<input type="file" id="Image" name="file">
<input type="button" id="SubmitButtonID" value="submit"/>