Laravel AJAX Image Upload Validation - ajax

I'm having trouble with validation on this AJAX POST for a file upload. Here's what I have so far. The 'required' validation keeps coming back telling me to select an image. When I console.log() the js variable with the image, it shows the filepath correctly.
View:
<form role="form" method="post" action="{{ route('profile.edit') }}" enctype="multipart/form-data">
<div class="form-group new-pic{{ $errors->has('profile-image') ? ' has-error' : '' }}">
<input type="file" id="newProfilePic" name="profile-image"/>
</div>
</form>
JS:
$('.btn-edit-profile-pic').click(function(e){
e.preventDefault();
var newPic = $('#newProfilePic').val();
$.ajax({
type: "POST",
url: "/profile-edit",
data: newPic,
error: function(data) {
var errors = $.parseJSON(data.responseText);
console.log(errors);
},
success: function() {
}
});
});
Controller:
if ($request->ajax())
{
$this->validate($request, [
'newPic' => 'required|image|max:4999'
],[
'required' => 'You must select an image',
'image' => 'The file must be an image',
'max' => 'The image file size must be less than 5mb'
]);
$extension = Input::file('profile-image')->getClientOriginalExtension();
$fileName = rand(11111,99999).'.'.$extension;
$image = Image::make(Input::file('profile-image'))
->orientate()
->resize(300, null, function ($constraint) {
$constraint->aspectRatio();
})
->save('images/profiles/'.$fileName);
Auth::user()->update([
'image_path' => $fileName,
]);
}

this is an intended behavior, you cant send upload file over XMLHTTPRequest, that is why you will always received the image file is required validation.
you can use an ajaxfileuploader plugins (They create a new form with in an iframe and submit it)
[http://www.sitepoint.com/10-jquery-ajax-file-uploader-plugins/]

Related

Stop previous ajax when new request is made using ajax

I am using Toast tui calendar https://nhn.github.io/tui.calendar/latest/ and I have an issue with ajax calling. It works correct except one thing, when I try to get data with the same option more than one times returns the new response but also still return the data of the previous response. please help me how can i resolve that thank u.
I think that there is something that I've missed.
controller
public function getBookingSlot(Request $request){
$userBookings = Booking::where('room_id',$request->room_id)->where('booking_status',1)->get();
foreach($userBookings as $booking){
$events [] = [
'id' => $booking->id,
'calendarId' => $booking->id,
'title' => 'Booked',
'category' => 'time',
'dueDateClass' => '',
'start' => $booking->start_datetime,
'end' => $booking->end_datetime,
];
}
return \Response::json([
'events' => $events ?? null
]);
}
html view
<div class="card mb-5 ">
<div id="calendar" style="height: 800px;"></div>
</div>
jquery
$(".butonSubmit").click(function(){
if($(".carousel-item").hasClass('active') ){
let room_id = $(".carousel-item.active").find('.room_id').val();
$.ajax({
url: "{{route('get-booking-slot')}}",
type:"POST",
data:{
"_token": "{{ csrf_token() }}",
room_id:room_id,
},
success:function(response){
calendar.createSchedules(
result = response.events
);
console.log(result);
},
error: function(response) {
console.log(error);
},
});
}
});
It is because you do not update the calendar after new request. Previous values are still there on the calender

Why does laravel $request->file return null?

I have a code that I am using in another app to upload files using Ajax which is working well.
Reusing this code in a new app with Jquery modal dialog is not working as expected. Below is my form:
{!! Form::open(['method' => 'POST', 'route' => ['auto-evaluation-documents.store'], 'files' => 'true', 'role' => 'form', 'id' => 'document_form']) !!}
<div class="modal-content" modal-transclude="" title="New Attachment">
<div class="form-group">
<input class="ng-scope" type="file" name="file" id="file">
</div>
</div>
{!! Form::close() !!}
Below is my modal dialog
var dialog;
dialog = $(".modal-content").dialog({
autoOpen: false,
height: 400,
width: 600,
modal: true,
buttons: {
"Save": uploadFile,
Cancel: function() {
$('#file').val('');
$('.c-fileupload__body').hide();
dialog.dialog( "close" );
}
},
close: function() {
//form[ 0 ].reset();
//allFields.removeClass( "ui-state-error" );
$('#file').val('');
$('.c-fileupload__body').hide();
}
});
$("#new_attachment_button").button().on( "click", function() {
dialog.dialog( "open" );
});
Below is the upload file function
function uploadFile() {
var document_form = $('#document_form');
var options = {
beforeSubmit: showRequest, // pre-submit callback
success: showResponse, // post-submit callback
uploadProgress: OnProgress, //upload progress callback
data: { 'document_type': 'file', 'evaluation_session_id':'2'},
url: document_form.attr('action'),
type: 'post',
dataType: 'json'
};
// attach handler to form's submit event
document_form.ajaxSubmit(options);
// return false to prevent normal browser submit and page navigation
return false;
}
// pre-submit callback
function showRequest(formData, jqForm, options) {
var file_msg = $('#file_msg');
file_msg.empty().hide();
var value = $('#file').fieldValue();
if (!value[0]) {
message = "<li>Please select a file to upload</li>";
file_msg.append(message).show();
return false;
} else {
formData.push({ 'name': 'file', 'value': value[0]});
return true;
}
}
In Laravel controller, I do:
public function store(Request $request)
{
$file = $request->file('file');
$return['success'] = true;
$return['file_name'] = $file;
return response()->json($return, 200, ['Content-Type' => 'text/html']);
}
However, when I check my console, the result I get for $request->file('file') is null
If I do $request->get('file'), I get C:\fakepath\banner-image.jpg
Why is $request->file('file') not working even though my form has enctype="multipart/form-data" ?
I have applied other solutions here with no success. Please help
You should try to dump $request->all(); to see if error is on front-end. If you have file named "file" error is in front-end/Angular.

Call to a member function store() on null on Laravel with Nuxt

I am currently having issues saving in Laravel from my Nuxt Application. I tried to perform the creating data from my postman and it works. I don't know what I missing here.
Controller
$book = Book::create([
'name' => $request->name,
'about' => $request->about,
// dd($request->file('image')),
'image' => $request->file('image')->store('images'),
]);
In my Nuxt template I have this
<form method="POST" enctype="multipart/form-data" #submit.prevent="save">
<div class="form-group">
<label for="name">Book Name</label>
<input
id="name"
v-model="editedItem.name"
type="text"
class="form-control"
placeholder="Book Name"
>
</div>
<div class="form-group">
<label for="image">Upload Book Cover</label>
<input
id="image"
name="image"
type="file"
accept="image/*"
class="form-control-file"
#change="onUpload"
>
</div>
<button type="submit" class="btn btn-primary">
Create Book
</button>
</form>
My nuxt methods
async save () {
try {
const formData = new FormData()
formData.append('name', this.editedItem.name)
formData.append('image', this.editedItem.imageurl.name)
await this.$axios.post('http://127.0.0.1:8000/api/createbookapi',
formData,
{
headers: {
enctype: 'multipart/form-data'
}
}
)
},
onUpload (e) {
this.editedItem.imageurl = e.target.files[0]
},
data: () => ({
editedItem: {
name: '',
imageurl: ''
}),
When I tried to save using postman, it works.
I don't know what I am missing here.
Call to a member function store() on null
becouse your file is null to avoid this add validation or make it optional
example of optional image
make sure database field is nullable
$book = Book::create([
'name' => $request->name,
'about' => $request->about,
'image' => $request->hasFile('image')
? $request->file('image')->store('images')
: null,
]);
for validation example
'image' => 'required|file', // it should check for file because file have class have store method

Vue.js with Laravel 8 API image upload throws 500 error

Below is this code for the image upload path; this is my template upload code.
<div class="form-group">
<div class="form-row">
<div class="col-md-6">
<input #change="onFileSelected" class="custom-file-input" type="file">
<small class="text-danger" v-if="errors.photo"> {{errors.photo[0]}} </small>
<label accept="image/*" class="custom-file-label" for="customFile" id="photo">Choose file</label>
</div>
<div class="col-md-6">
<img :src="form.photo" style="height: 40px; width:40px;">
</div>
</div>
</div>
This is the click event's function; this is the data I want to pass to my API.
ata() {
return {
form:{
name: null,
email: null,
address: null,
salary: null,
joining_date: null,
nid: null,
phone: null,
photo: null
},
errors: {
}
}
},
methods: {
onFileSelected(event){
// console.log(event)
let file = event.target.files[0];
if(file.size > 1048770) {
// Notification.image_validation()
Toast.fire({
icon: 'error',
title: 'upload image less than 1MB'
})
}else {
//console.log(form)
let reader = new FileReader();
reader.onload = event =>{
this.form.photo = event.target.result
console.log(event.target.result)
};
reader.readAsDataURL(file)
}
},
The following is the code I push my date to.
employeeinsert()
{
console.log(this.form.photo)
axios.post('/api/employee', this.form)
.then(() => {
// console.log(this.form)
// this.$router.push({name: 'employee'})
// Toast.fire({
// icon: 'success',
// title: 'employee add success'
// })
})
.catch(error => this.errors = error.response.data.errors)
}
These are the Laravel 8 backend validations. Here I try to get the request image and name change and try to save my public folder.
if ($request->photo) {
$position = strpos($request->photo, ';');
$sub = substr($request->photo, 0, $position);
$ext = explode('/', $sub)[1];
$name = time() . "." . $ext;
$img = Image::make($request->photo)->resize(240, 200);
$upload_path = 'backend/employee';
$inage_url = $upload_path . $name;
$img->save($inage_url);
return console . log($inage_url);
Employee::insert([
'name' => $request->name,
'email' => $request->email,
'address' => $request->address,
'salary' => $request->salary,
'joining_date' => $request->joining_date,
'nid' => $request->nid,
'phone' => $request->phone,
'photo' => $last_image
]);
When I upload an image, I get a 500 error.
Here's the 500 error with any logs.
I have no idea why it throws 500. Please help to resolve this.
Few things which can cause 500 error as visible in your code are
return console.log($inage_url): console.log() is javascript not PHP
$inage_url = $upload_path.$name; it should be $inage_url = $upload_path.'/'.$name otherwise $img->save($inage_url); can cause error as path is not well formed
Not clear where the $last_image comes from in'photo' => $last_image

Do form validation with jquery ajax in codeigniter

How can i do form validation in codeigniter if i don't want to refresh the page?
Basically i do this:
$config = array(
array(
'field' => 'c_name',
'label' => 'Name',
'rules' => 'trim|required'
),
array(
'field' => 'c_job',
'label' => 'Job',
'rules' => 'trim|required',
)
);
$this->form_validation->set_rules($config);
if($this->form_validation->run() == true)
{
$this->load->model('model');
//.....
}
else{
$this->load->view('view');
}
But if i send data with ajax and the page doesn't refresh, How can i do form validation?
Edit:
Thanks # Amra Kojon. That's good and works but the new problem is this:
if ($this->form_validation->run() == FALSE) {
echo validation_errors();
}
else {
//echo 'hi';
$value = $this->input->post('value');
$values = array(
'c_name' => $value['c_name'],
'c_job'=> $value['c_job'],
'c_address'=> $value['c_address'],
'c_phone'=> $value['c_phone'],
'c_mail'=> $value['c_mail'],
'c_state'=> $value['c_state'],
'c_intrest'=> $value['c_intrest'],
'c_added_info'=> $value['c_added_info']
);
$add = $this->customers_model->add_customer($values);
echo $add;
}
If i just say echo "something" in the else part, It works and if the validation were OK, It echo hi but if i write theme in database (Which the value array has data and in not ajax way, it insert date), It doesn't work and the else part isn't working!!!
If you gave your JS- jquery Ajax code it would more efficient to understand your problem.. Don't worry! Try my following instruction...
Get get form value and pass to form as
$(document).ready(function(){
var dataString = $("#FormId").serialize();
var url="ControllerName/MethodName"
$.ajax({
type:"POST",
url:""+url,
data:dataString,
success:function (data) {
alert(data);
}
});
})
Controller :
Load library form_validation in construct as ...
$this->load->library('form_validation');
$this->load->helper('form');
Now write your controller as ...
function MethodName {
$this->form_validation->set_error_delimiters('', '');
$this->form_validation->set_rules('fname','First Name', 'required');
$this->form_validation->set_rules('lname','Last Name', 'required');
$this->form_validation->set_rules('email','Email Address','required|valid_email|is_unique[sec_users.email]');
if ($this->form_validation->run() == FALSE) {
echo validation_errors();
}
else {
// To who are you wanting with input value such to insert as
$data['frist_name']=$this->input->post('fname');
$data['last_name']=$this->input->post('lname');
$data['user_name']=$this->input->post('email');
// Then pass $data to Modal to insert bla bla!!
}
}
I know your question is a year old but you can use this for the latest bootstrap with codeigniter
<?php
class Yourcontroller extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->library('form_validation');
}
public function index() {
$this->load->view('template/register');
}
public function validate() {
$json = array();
$this->form_validation->set_rules('username', 'Username', 'required');
$this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email');
$this->form_validation->set_rules('password', 'Password', 'required|min_length[5]');
$this->form_validation->set_rules('confirm_password', 'Confirm Password', 'required|matches[password]');
$this->form_validation->set_rules('code', 'Login Code', 'required|numeric|min_length[4]||max_length[8]');
$this->form_validation->set_message('required', 'You missed the input {field}!');
if (!$this->form_validation->run()) {
$json = array(
'username' => form_error('username', '<p class="mt-3 text-danger">', '</p>'),
'email' => form_error('email', '<p class="mt-3 text-danger">', '</p>'),
'password' => form_error('password', '<p class="mt-3 text-danger">', '</p>'),
'confirm_password' => form_error('confirm_password', '<p class="mt-3 text-danger">', '</p>'),
'code' => form_error('code', '<p class="mt-3 text-danger">', '</p>')
);
}
$this->output
->set_content_type('application/json')
->set_output(json_encode($json));
}
}
Ajax Script
<script type="text/javascript">
$( document ).ready(function() {
$('#error').html(" ");
$('#form-submit-button').on('click', function (e) {
e.preventDefault();
$.ajax({
type: "POST",
url: "<?php echo site_url('yourcontroller/validate');?>",
data: $("#form").serialize(),
dataType: "json",
success: function(data){
$.each(data, function(key, value) {
$('#input-' + key).addClass('is-invalid');
$('#input-' + key).parents('.form-group').find('#error').html(value);
});
}
});
});
$('#form input').on('keyup', function () {
$(this).removeClass('is-invalid').addClass('is-valid');
$(this).parents('.form-group').find('#error').html(" ");
});
});
</script>
Full View Code
<div class="container">
<div class="row">
<div class="col-sm-6 ml-auto mr-auto m-auto">
<div class="card mt-5">
<h5 class="card-header"></h5>
<div class="card-body">
<?php echo form_open('agent/register', array('id' => 'form', 'role' => 'form'));?>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<?php echo form_input('username', '', array('class' => 'form-control', 'placeholder' => 'Enter Agent Username', 'id' => 'input-username'));?>
<div id="error"></div>
</div>
<hr/>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<?php echo form_input('email', '', array('class' => 'form-control', 'placeholder' => 'Enter Agent Email', 'id' => 'input-email'));?>
<div id="error"></div>
</div>
<hr/>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<?php echo form_password('password', '', array('class' => 'form-control', 'placeholder' => 'Enter Password', 'id' => 'input-password'));?>
<div id="error"></div>
</div>
<hr/>
</div>
<div class="col-sm-6">
<div class="form-group">
<?php echo form_password('confirm_password', '', array('class' => 'form-control', 'placeholder' => 'Enter Confirm Password', 'id' => 'input-confirm_password'));?>
<div id="error"></div>
</div>
<hr/>
</div>
</div>
<hr/>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<button type="button" class="btn btn-block btn-dark" id="form-submit-button">Register Agent</button>
</div>
</div>
</div>
<?php echo form_close();?>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$( document ).ready(function() {
$('#error').html(" ");
$('#form-submit-button').on('click', function (e) {
e.preventDefault();
$.ajax({
type: "POST",
url: "<?php echo site_url('yourcontroller/validate');?>",
data: $("#form").serialize(),
dataType: "json",
success: function(data){
$.each(data, function(key, value) {
$('#input-' + key).addClass('is-invalid');
$('#input-' + key).parents('.form-group').find('#error').html(value);
});
}
});
});
$('#agent-register-form input').on('keyup', function () {
$(this).removeClass('is-invalid').addClass('is-valid');
$(this).parents('.form-group').find('#error').html(" ");
});
});
</script>
If you are aware about passing data with ajax, then the work flow is as follows.
1) Send form data through ajax to your controller.
2) Do form validation as of now.
3) If success then "echo" value 1
4) If failure, echo value 0
So that using the value in echo, you can determine whether the validation fails or not. I can give you an example if you need
Sample ajax code
$('#form').on('submit', function(e){
e.preventDefault();
var data = $(this).serialize();
$.ajax({
url: 'your url',
type: 'POST',
data: data,
success: function(data){
if(data == 1){
$('#form')[0].reset();
alret('success');
}
else if(data == 0){
alret('failed');
}
},
error: function(){
alert('error');
}
});
});
Create MY_Form_validation in libraries folder
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation {
private $json = array();
private $opts = array();
function get_json($extra_array = array(),$error_array=array())
{
if(count($extra_array)) {
foreach($extra_array as $addition_key=>$addition_value) {
$this->json[$addition_key] = $addition_value;
}
}
$this->json['options'] = $this->opts;
if(!empty($error_array)){
foreach($error_array AS $key => $row)
$error[] = array('field' => $key, 'error' => $row);
}
foreach($this->_error_array AS $key => $row)
$error[] = array('field' => $key, 'error' => $row);
if(isset($error)) {
$this->json['status'] = 'error';
$this->json['errorfields'] = $error;
} else {
$this->json['status'] = 'success';
}
return json_encode($this->json);
}
}
Call this function in controller if validation failed:
echo $this->form_validation->get_json();
You get the response with form fieldname and errormessage
Example:
{"options":[],"status":"error","errorfields":[{"field":"email","error":"The Mobile Number\/Email\/Username field is required."},{"field":"password","error":"The Password field is required."}]}
Try this is my working (Codeigniter 3.0) basic example to achieve what you want do
include filename.js in your view
document.getElementById("yourForm").reset();
$(document).ready( function() {
var yourForm = $('#yourForm');
yourForm.submit( function(event) {
event.preventDefault();
$.ajax( {
type: 'POST',
url: yourForm.attr( 'action' ),
data: yourForm.serialize(),
success: function(data) {
if (data.code == '200') {
$('#message').html(data.message);
document.getElementById("yourForm").reset();
}
},
error: function(data) {
var response = data.responseText;
var obj = jQuery.parseJSON(response);
if (obj.code == '500') {
var i;
for (i = 0; i < obj.field.length; i++) {
name = obj.field[i];
$('.label-'+name).addClass('label-error');
errors = JSON.stringify(obj.validation);
validate = jQuery.parseJSON(errors);
$('.helper-'+name).html(validate[name]);
}
}
}
} );
} );
} );
view HTML form example
In this example in am using className you can use id as well change filename.js file accordingly
<form id="yourForm" action="base_url/controller/function_name" action="POST">
// Important text after className "label-" & "helper-" must be input name
<label class="label-firstName">Name</label>
<input type="text" name="firstName" />
<span class="helper-firstName"></span>
</form>
<div id="message"></div>
controller PHP code
public function function_name()
{
if(!empty($_POST)) {
$this->load->library('form_validation');
$this->form_validation->set_rules('firstName','First Name','required|max_length[16]');
if($this->form_validation->run())
{
$params = array(
'firstName' => $this->input->post('firstName'),
);
// Model returning $data['newRecord'] with $params and insertId
$data['newRecord'] = $this->Record_model->newRecord($params);
$reply = array();
$reply['code'] = 200;
$reply['record'] = array(
'insertId' => $data['newRecord']['insertId'],
'firstName' => $data['newRecord']['firstName']
);
$reply['message'] = 'Hello, ' .$data['newRecord']['firstName']. ' - We have received your message. ' .$data['newRecord']['insertId']. ' is your reference ID, for this communication.';
header('Content-Type: application/json; charset=UTF-8');
print json_encode($reply);
}
else {
$validation = $this->form_validation->error_array();
$field = array();
foreach($validation as $key => $value) {
array_push($field,$key);
}
$reply = array(
'code' => 500,
'field' => $field,
'validation' => $validation,
'message' => 'Submission failed due to validation error.'
);
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Problem', true, 500);
header('Content-Type: application/json; charset=UTF-8');
print json_encode($reply);
}
}
else {
$reply = array();
$reply['code'] = 403;
$reply['message'] = 'No Direct Access Allowed.';
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden', true, 403);
header('Content-Type: application/json; charset=UTF-8');
print json_encode($reply);
}
}
If using ajax,...you can't use form_validation library
So you can validate on client side using jquery ...and on server side should use if statement to check submitted data

Resources