Uploading multiple dynamic files to laravel from vue - javascript

I'm trying to upload multiple files with it's respective data from vue to laravel. I'm getting the files in vue (on vue console) but when submitting the form and doing dd($request['new_members']); on the laravel controller, it returns the result below:
The other data is available but the file value is gone.
Vue
<div class="row mt-2" v-for="(new_member,index) in new_members" :key="index">
<div class="col-md-4">
<label>NAME</label>
<input class="form-control" type="text" v-model="new_member.name" required/>
</div>
<div class="col-md-4">
<label>POSITION</label>
<input class="form-control" type="text" v-model="new_member.position" required/>
</div>
<div class="col-md-4">
<label>IMAGE</label>
<input type="file" #change="onFileChange(index,$event)" name="file" ref="fileInput" required/>
</div>
</div>
<button class="btn btn-primary col-md-2 col-12 rounded-0 float-right" #click.prevent="addMoreMember()">ADD MORE</button>
<script>
data(){
return{
new_members:[{
name:'',
position:'',
file:''
}]
}
},
methods:{
addMoreMember(){
this.new_members.push({name:'',position:'',file:''})
},
onFileChange(index,$event) {
this.new_members[index].file = $event.target.files[0]
},
submit(){
let form = new FormData()
form.append('new_members',JSON.stringify(this.new_members));
form.append('content_team', this.content_team);
axios.post('/api/mainpage/addNewMember',form).then(res=>{
})
},
}
</script>

For multiple file uploading concepts,
You need to create an API service for upload files only and returning that response return string for accessing uploaded file path,
For every file uploading, You need to call this API services that you created.
And the final page submission you just send the file path string where you got from the file uploading API services
I hope you are getting my points ❤

Related

jqWidgets: How can I post an HTML form inside a jqxWindow?

I created the following HTML form inside a jqxWindow widget for a Laravel project:
<div id="provinceWindow">
<div id="provinceWindowHeader"></div>
<div id="provinceWindowContent">
<form id="provinceForm" method="POST" action="{{route('province.store')}}">
{{ csrf_field() }}
<input type="hidden" name="provinceId" id="provinceId" value=""/>
<div class="form-group row">
<div class="col-6"><label>English province name</label></div>
<div class="col-6"><input type="text" name="provinceNameEn" id="provinceNameEn" maxlength="20"/></div>
</div>
<div class="form-group row">
<div class="col-6"><label>Spanish province name</label></div>
<div class="col-6"><input type="text" name="provinceNameSp" id="provinceNameSp" maxlength="20"/></div>
</div>
<br/>
<div class="form-group row justify-content-center">
<input type="button" value="Submit" id="submitBtn" class="btn btn-sm col-3" />
<span class="spacer"></span>
<input type="button" value="Cancel" id="cancelBtn" class="btn btn-sm col-3" />
</div>
</form>
</div>
</div>
This is the javascript file:
$(document).ready(function () {
var datarow = null;
$.ajaxSetup({
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}
});
//-----------------------------
// Window settings
//-----------------------------
$('#provinceWindow').jqxWindow({
autoOpen: false,
isModal: true,
width: 400,
height: 160,
resizable: false,
title: 'Province name',
cancelButton: $('#cancelBtn'),
initContent: function () {
$('#submitBtn').jqxButton();
$('#submitBtn').on('click', function () {
$('#provinceForm').submit();
});
}
}).css('top', '35%');
The file routes\web.php has only one resourse route defined for this page:
// Routes for province maintenance
Route::resource('province', 'provinceController');
Checking the available routes with php artisan route:list command, I get these:
Method URI Name Action
GET|HEAD / APP\Http\Controllers\homeController#index
GET|HEAD province province.index APP\Http\Controllers\provinceController#index
POST province province.store APP\Http\Controllers\provinceController#store
GET|HEAD province/create province.create APP\Http\Controllers\provinceController#create
GET|HEAD province/{province} province.show APP\Http\Controllers\provinceController#show
PUT|PATCH province/{province} province.update APP\Http\Controllers\provinceController#update
DELETE province/{province} province.destroy APP\Http\Controllers\provinceController#destroy
GET|HEAD province/{province}/edit province.edit APP\Http\Controllers\provinceController#edit
My controller action:
public function store(Request $request)
{
$fields = $request->all();
if ($request->provinceId == '') {
$province = new province($fields);
$validator = Validator::make($fields, $province->rules());
if ($validator->fails()) {
return redirect('')->withErrors($validator)->withInput();
}
else {
$province->save();
}
return view('province/index');
}
}
The form is shown on top of a jqxGrid widget, as a modal window, in order to capture the required information and perform the CRUD operations for the corresponding DB table.
The problem is, when I click the "Submit" button the window is closed and nothing else happens. The form is not posted to the indicated action and the data entered get lost.
It does not matter if I initialize the submitBtn inside the initContent or outside of it. The form is never posted.
I also tried the Close event of the jqxWindow to no avail.
If I take a look to the generated HTML it looks like this:
<form id="provinceForm" method="POST" action="http://mis:8080/province">
<input type="hidden" name="_token" value="Y9dF5PS7nUwFxHug8Ag6PHgcfR4xgxdC43KCGm07">
<input type="hidden" name="provinceId" id="provinceId" value="">
<div class="form-group row">
<div class="col-6">
<label>English province name</label>
</div>
<div class="col-6">
<input type="text" name="provinceNameEn" id="provinceNameEn" maxlength="20">
</div>
</div>
<div class="form-group row">
<div class="col-6">
<label>Spanish province name</label>
</div>
<div class="col-6">
<input type="text" name="provinceNameSp" id="provinceNameSp" maxlength="20">
</div>
</div>
<br>
<div class="form-group row justify-content-center">
<input type="button" value="Submit" id="submitBtn" class="btn btn-sm col-3 jqx-rc-all jqx-button jqx-widget jqx-fill-state-normal" role="button" aria-disabled="false">
<span class="spacer"></span>
<input type="button" value="Cancel" id="cancelBtn" class="btn btn-sm col-3">
</div>
</form>
Pressing the submit button takes me to the home page and nothing gets added to the DB table.
I guess the issue has something to do with Laravel routes because I get no errors.
What is missing or what is wrong with this approach?
Any light is appreciated.
Alright, because I erroneously added in my Model a validation, that was not needed, for a column (there was already a constraint defined at the DB table level), it was not possible to fulfill the validator when saving a new record. I commented that line in my Model and, that was it!
protected $rules = array(
'provinceNameEn' => 'required|alpha|max:20',
'provinceNameSp' => 'required|alpha|max:20'
//'deleted' => 'required|in:M,F' // This is already validated in a DB constraint.
);
I noticed the control was returned to my home page but without any message or error, but if you pay attention to my controller it was precisely the behavior programmed. However, there is no implementation to display the error messages, so I added dd($validator); before that return statement. There I read the message and finally found the solution.

How use Vuesax upload component in Laravel/Vue.js project?

I'm working on this project base on tutorials around web and YOUTUBE .
My problem is that base on tutorial I've got a from like this:
<form class="form-horizontal">
<div class="form-group">
<label for="mellicode_front_url" class="col-sm-2 control-label">scan</label>
<div class="col-sm-12">
<input type="file" #change="updateMelliCodeFrontScan" name="mellicode_front_url" class="form-input" >
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-12">
<button #click.prevent="saveMelliCodeFrontScan" type="submit" class="btn btn-success">submit scan</button>
</div>
</div>
</form>
as u can see in this code when i opened a IMAGE file i use #change method, then I'll use click.prevent in submit button to upload image into host.
problem is I'm using component from this site :
https://lusaxweb.github.io/vuesax/components/upload.html
which it's using this type of code for uploading :
<vs-upload action="https://jsonplaceholder.typicode.com/posts/" #on-success="successUpload" />
I've changed and removed action with onChange and other things but just because i'm beginner i'm sure i didn't properly. so what i'm trying to do is implement those #change="updateShenasnameScan" & #click.prevent="saveShenasnameScan" into this vs-upload component.
I think that component not supporting the binding or form object to assign the files to it.
But in the backend in Laravel you can get files by $_FILES, this will gives you an object of files that you can use it and store the files simply on the server.
Here is my work on this upload system
Laravel Function
public function store(Request $request)
{
$stored = [];
$files = $_FILES;
foreach ($files['archive']['tmp_name'] as $key => $value) {
$file = file_get_contents($value);
if(Storage::disk('local')->put('archive/'. $files['archive']['name'][$key], $file)){
$stored[$key] = 'archive/'. $files['archive']['name'][$key];
}else{
$stored[$key] = $files['archive']['error'][$key];
}
}
return $stored;
}
And the VUE code, that you can find more about it here https://lusaxweb.github.io/vuesax/components/upload.html#automatic
<vs-upload multiple fileName='archive[]' automatic action="/api/archive" #on-success="successUpload" />
And the $_FILES data as bellow

Ajax form not submitting form rails

I'm using a super basic google form on my website. I'm using this website to extract the HTML to display it on my website - http://stefano.brilli.me/google-forms-html-exporter/
Once I hit submit, nothing happens. The page is just locked. I'm trying to resubmit it to another page. Here is my code
<div class="row">
<form action="https://docs.google.com/forms/d/e/1FAIpQLSfJQ9EkDN8aggSL9AEB2PK4BGiZgBzLDbS1IPppfSkU1zy-oA/formResponse"target="_self" id="bootstrapForm" method="POST">
<div class="col-sm-6 col-md-3">
<input id="679075295" type="text" name="entry.679075295" class="form-control" >
</div>
<div class="col-sm-6 col-md-3">
<input id="897968244" type="text" name="entry.897968244" class="form-control" >
</div>
<div class="col-sm-6 col-md-3">
<input id="685661947" type="text" name="entry.685661947" class="form-control" >
</div>
<input id="503500083" type="hidden" name="entry.503500083" value="<%= #investment.id %>" >
<div class="col-sm-6 col-md-3">
<button type="submit" value"submit" class="btn btn--primary type--uppercase" >Get Started</button>
</div>
</form>
Here is the ajax script
<script>
$('#bootstrapForm').submit(function (event) {
event.preventDefault()
var extraData = {}
$('#bootstrapForm').ajaxSubmit({
data: extraData,
dataType: 'jsonp', // This won't really work. It's just to use a GET instead of a POST to allow cookies from different domain.
error: function () {
// Submit of form should be successful but JSONP callback will fail because Google Forms
// does not support it, so this is handled as a failure.
alert('Form Submitted. Thanks.')
// You can also redirect the user to a custom thank-you page:
window.location = 'http://reif.com.au/thankyou'
}
})
})
</script>
</div>
Feeling a little silly on this one. Essentially i didn't copy over all of the scripts. I was rushing through.. ALWAYS number 1 error!
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.2.2/jquery.form.min.js" integrity="sha256-2Pjr1OlpZMY6qesJM68t2v39t+lMLvxwpa8QlRjJroA=" crossorigin="anonymous"></script>
This is what i needed to add, it now successfully submits and redirects!

Empty values are not submitting in Angular 4 form

I working on Angular 4 project. I am using smart table and form in it.
<div class="row">
<div class="col-lg-12">
<nb-card>
<nb-card-header>Default Inputs</nb-card-header>
<nb-card-body >
<form #f="ngForm" (ngSubmit) = "addNewStudent(f)" >
<div class="row full-name-inputs">
<div class="col-sm-6 input-group">
<input type="text" placeholder="First Name" class="form-control" name="firstName" [(ngModel)]="data.firstName" />
</div>
<div class="col-sm-6 input-group">
<input type="text" placeholder="Last Name" class="form-control" name="lastName" [(ngModel)]="data.lastName" />
</div >
<div class="col-sm-6 input-group">
<input type="text" placeholder="ID" class="form-control" name="id"[(ngModel)]="data.id" [required]=false />
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<button type="cancel" class="btn ">Cancel</button>
</form>
</nb-card-body>
</nb-card>
</div>
</div>
On edit button of table the form is open and shows the whole data of that row in that form, similar form button will be open on add new data in which the data should be added but if I enter only one data and submit it it does not add it it requires all fields.
The add function is as follows:
addNewStudent(f: NgForm)
{
console.log(f.value);
if(this.isAddPage)
{
this.service.addNewEnquiry(f.value);
console.log("addenquiry");
}
else{
this.service.editEnquiry(f.value);
console.log("editenquiry");
}
this.router.navigate(['pages/dashboard1']);
}
The addNewEnquiry function in service is as follows:
addNewEnquiry(data)
{
this.af.list('/enquirydata/').push(data);
}
When I enter all fields it added it to the firebase but when I doesn't fill all fields it shows me error.
ERROR Error: Reference.push failed: first argument contains undefined
in property 'enquirydata.lastName
When you want to push an object into Firebase, you can't have values of the properties equals undefined. Firebase accepts value or null only. Else you always show this error.
In your case :
{ id:undefined, lastName:undefined, firstName:undefined }
To resolve your issue :
public data:any = { id:null, lastName:null, firstName:null };
Before inserting it into your list, you can eliminate undefined ones from object.
addNewEnquiry(data)
{
var newData = data.filter(resp=>{
if(resp.firstName && resp.lastName) {
return resp;
}
})
this.af.list('/enquirydata/').push(newData);
}

Best way to upload files using Ajax and before submitting

I have a form with multiple fields but also a file upload. I am able to upload multiple files.
I also know that it is possible to upload files with AJAX.
So I would like to upload my files using ajax while i'm filling in every other field. But how would I link the already uploaded images then? And also prevent the images to be uploaded again?
This is the form:
<form id="form_validation" method="POST" action="{{route('storeexpense')}}" enctype="multipart/form-data">
{{ csrf_field() }}
<div class="form-group form-float">
<div class="form-line">
<input type="text" class="form-control" name="description" required>
<label class="form-label">Omschrijving</label>
</div>
</div>
<div class="form-group form-float">
<div class="form-line">
<input type="number" class="form-control" name="amount" required>
<label class="form-label">Bedrag</label>
</div>
</div>
<div class="form-group form-float">
#foreach ($types as $type)
#if ($type->id === 1)
<input name="transactiontype" type="radio" id="rdio{{$type->id}}" value="{{$type->id}}" checked />
<label for="rdio{{$type->id}}">{{$type->description}}</label>
#else
<input name="transactiontype" type="radio" id="rdio{{$type->id}}" value="{{$type->id}}" />
<label for="rdio{{$type->id}}">{{$type->description}}</label>
#endif
#endforeach
</div>
<div class="form-group form-float">
<div class="form-line">
<input type="text" class="datepicker form-control" name="date" placeholder="Please choose a date..." required>
<!-- <label class="form-label">Datum</label> -->
</div>
</div>
<div class="form-group demo-tagsinput-area">
<div class="form-line">
<input type="text" class="form-control" id="tagsinput" data-role="tagsinput" placeholder="Labels" name="tags" required>
</div>
</div>
<div class="form-group form-float">
<div class="form-line">
#if (count($errors) > 0)
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
#endif
<input type="file" name="attachments[]" multiple class="custom-file-control"/>
</div>
</div>
<button class="btn btn-primary waves-effect" type="submit">SAVE</button>
</form>
This is the PHP code that saves the information from the form:
public function store(UploadRequest $request)
{
// Save new transaction in database
$transaction = new Transaction;
$transaction->description = $request->description;
$transaction->amount = $request->amount;
$input = $request->date;
$format = 'd/m/Y';
$date = Carbon::createFromFormat($format, $input);
$transaction->date = $date;
$transaction->transactiontype_id = $request->transactiontype;
$transaction->user_id = Auth::id();
$transaction->save();
// Put tags in array
$inputtags = explode(",", $request->tags);
// Loop through every tag exists
// EXISTS: get ID
// NOT EXISTS: Create and get ID
foreach ($inputtags as $inputtag)
{
$tag = Tag::firstOrCreate(['description' => $inputtag]);
$transaction->tags()->attach($tag->id); //Put the 2 ID's in intermediate table ('tag_transaction')
}
//Check if there are files
if (!is_null($request->attachments))
{
//Loop through every file and upload it
foreach ($request->attachments as $attachment) {
$filename = $attachment->store('attachments');
// Store the filename in the database with link to the transaction
Attachment::create([
'transaction_id' => $transaction->id,
'path' => $filename
]);
}
}
Thanks,
Bart
It sounds like you want to make a fancy form that starts uploading the file as soon as you choose it and meanwhile the user can continue filling the rest of the form. If so, I'd do it like this:
Implement your main text/data form, eg.
<form method="POST" action="/save-data-endpoint.php">
<input name="email" type="text" />
<button type="submit>Submit</button>
</form>
Next to it, a form for the images. eg.
<form method="POST" class="file-upload-form" action="/save-file.php">
<input name="my-file" type="file" />
<!-- note that we wont show a submit button -->
</form>
For the user, it all looks like the same form but clicking the submit button will send only the data to the save-data-endpoint.php. Now we need some js to control this madness (I'll use jQuery for brevity). But you can use FileReader api in js, ajax progress tracking to make it even fancier. See https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications for more.
$(function(){ // run when document is ready
// listen when the input changes (when a file is selected)
$('.file-upload-form').on('change', function(e){
// file has been selected, submit it via ajax
// show some kind of uploading indication, eg. a spinner
$.ajax({
type:'POST',
url: $(this).attr('action'),
data: new FormData(this),
cache:false,
contentType: false,
processData: false,
success:function(data){
// the save-file.php endpoint returns an id and/or a url to the saved/resized/sanitized image
console.log(data.id, data.url);
// we then inject this id/url, into the main data form
var $hiddenInput = $('<input type="hidden" name="uploads[]" value="'+data.id+'">');
$('.main-form').append($hiddenInput);
// show a thumbnail maybe?
var $thumbnail = $('<img src="'+data.url+'" width="20" height="20" />');
$('.main-form').append($thumbnail);
// hide spinner
// reactivate file upload form to choose another file
$('.file-upload-form').find('input').val('');
},
error: function(){
console.log("error");
}
});
});
});
Your backend will get the images as they are selected, one by one. You then save them and return an id and/or a url to the image to be used in the success handler in js. After adding some images your main form should look something like this:
<form method="POST" action="/save-data-endpoint.php">
<input name="email" type="text" />
<button type="submit>Submit</button>
<input type="hidden" name="uploads[]" value="x">
<img src="...x.jpg" width="20" height="20" />
<input type="hidden" name="uploads[]" value="y">
<img src="...y.jpg" width="20" height="20" />
</form>
Now when the user fills the remaining fields and clicks submit, your server will get all the data along with an array called uploads which contains all the image ids/paths you have already saved. You can now store this data and relate it to the files.
I wont go deeper on the backend side as it can be implemented on any language. In summary the basic flow would be:
send files one at a time to a save file endpoint that returns a file identifier (can be an id, hash, full path to image, etc)
js injects those ids into the main form
the main form is submitted to a save data endpoint that returns a success or error message and stores + relates all the data in your preferred method of storage.
Hope it helps!

Categories

Resources