Uploading multiple files with angular-file-upload - angularjs

I'm using angular-file-upload to upload images along with form data to my server. I've been able to do that successfully one image at a time.
My problem is that in my form I need to upload two images, using separate inputs (as well as send along other form data). My reasoning for using separate inputs is that one of my images is a thumbnail image and the other is a hero image. I need the ability to distinguish between them and insert the file paths for each into their respective columns in my database.
I read through this github issue that went through how to upload multiple files using the same input, but I wasn't able to find anything about uploading multiple files using different inputs. Maybe I'm misunderstanding them though.
Right now, if I try to select a header image, it only changes the value of the thumbnail image.
Here is my form:
<form>
...(other text form inputs above)...
<div class="form-group">
<label class="col-sm-2 control-label"> Teaser</label>
<div class="col-sm-8>
<input class="form-control" filestyle="" accept=".png,.gif,.jpg,.jpeg" data-button-text="Choose image" type='file' data-classbutton='btn btn-default' data-classinput="form-control inline" nv-file-select='' uploader='uploader' options="{'field': 'thumbnail_url'}"
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"> Header Image</label>
<div class="col-sm-8>
<input class="form-control" filestyle="" accept=".png,.gif,.jpg,.jpeg" data-button-text="Choose image" type='file' data-classbutton='btn btn-default' data-classinput="form-control inline" nv-file-select='' uploader='uploader' options="{'field': 'header_url'}"
</div>
</div>
</form>
And here is how I am sending the file to my server (on the onCompleteAll callback I am sending my form data to the server):
$scope.uploader = new FileUploader({
url: '/laravel/public/admin/events/thumbnail_url/file_upload',
alias: 'files',
headers: {
// 'X-CSRF-Token': n/a
},
onBeforeUploadItem: function(item) {
/* Laravel file name alias */
item.alias = 'file';
},
onSuccessItem: function(fileItem, response, status, headers) {
$scope.newEventForm[fileItem.field] = '/laravel/public/uploads/events/' + response.filename;
},
onCompleteAll: function() {
/* Now ready to save form data */
AdminEvent.save($scope.newEventForm).$promise.then(function(response) {
$scope.events.push(response.data);
toaster.pop('success', 'Added', 'Event added successfully.');
});
}
});

I faced the same issue with ng-file-upload but I did not used angular-file-upload.
So may be this solution helpful for you.
In my app I have user profile image and background image.
where profile image input value I send with file option of ng-file-upload but it did not provide other option to send second file input value.
TO resolve that What I did
Created second file input and used that input model same as my table attribute like ng-model="user.bg_avatar" where bg_avatar is my background image attribute in rails.
Now You can get second file input value with user object(user.bg_avatar) in angular controller which we will send to rails and when rails get it save that with other user attribute.
But don,t forgot to permit this attribute.

Related

ngFileSelect with 2 images upload in a form

I am using the angular-file-upload.js .I would like to upload the 2 images in a form, 2 different file uploads and one form submit button.
In my controller:
var uploader = $scope.uploader = $fileUploader.create({
scope: $scope,
url:'upload.php',
autoUpload : true
});
uploader.addToQueue([uploader.queue[0].file]);
uploader.queue[0].upload();
amd my html is:
<input type="file" ng-file-select class="form-control"
ng-model="file_course_thumb_image" accept=".png, .jpg, .jpeg" />
<input type="file" ng-file-select class="form-control"
ng-model="file_course_thumb_image2" accept=".png, .jpg, .jpeg" />
when trying to upload only second file is uploaded ,but not both first and second files.
Any suggestions ..
I have fixed the issue by changes in the angular-file-upload.js #author Danial #version 1.2.8 .In addToQueue function add the condition to empty the queue .
if(this.queue.length == 0) {
this.queue = [] }
which can enable us to uploads multiple images at the time of form submit.

angular submitting only form data not whole model

I'm submitting form data to my API but my model contains my whole object. I should really only submit the updates, correct?
So,
my item is retrieved by Id, which I don't need to show to the user (hidden field).
I'll show the user the title of item so they know what they're editing, but I won't make it editable (read-only).
I'll expose description so the user can edit it and save.
(Imagine a larger form - a half dozen more read-only fields and a half dozen more editable fields.)
Correct me if I'm wrong but, when sending to my API, I should not be sending the entire item object. The db already has title, why put it in the payload if its just going to be thrown away?
So, I should really only be sending the values of the editable fields.
I'm trying to figure out the proper way of separating the model from the form data so I submit the latter, not the former. If this is not best practice, please correct me.
Controller:
.controller('editItemController', ['$stateParams',
function($stateParams) {
var vm = this;
vm.getItem = function () {
$http.get('/api/Items/' + $stateParams.id).then(function (response) {
vm.item = response.data;
});
};
vm.saveChanges = function () {
vm.submitted = true;
if (vm.detailsForm.$valid) {
$http.put('/api/Items/' + $stateParams.id, vm.item).then(function (response) {
});
}
};
vm.getItem();
}
View:
<form name="itemVm.detailsForm" ng-controllerAs="itemVm">
<input type="hidden" name="Id" ng-model="itemVm.item.Id" />
<div class="form-group">
<label for="title" class="control-label col-xs-3">Title:</label>
<div class="col-xs-9">
<input type="text" class="form-control" readonly="readonly" id="title" value="{{ itemVm.item.Title }}">
</div>
</div>
<div class="form-group">
<label for="description" class="control-label col-xs-3">Description:</label>
<div class="col-xs-9">
<input type="text" class="form-control" name="description" ng-model="itemVm.item.Description" required>
</div>
</div>
<button ng-click="itemVm.saveChanges()">Save Changes</button>
</form>
For a standard REST API, you should be sending the entire object. The entire idea behind REST is that you transfer representations of the state of an object, hence representational state transfer. As such, it should be a complete representation, not a portion.
There are multiple ways to circumvent this if you'd really like, and most have to do with the back end, not the front end.
Either create an ad hoc endpoint to take in the one parameter and update the persistent object accordingly. (Not recommended).
If you want to send partial data (which I think is a good idea some times depending on the size of the object), you should handle that on the back end accordingly.
See here.

Upload files with Angular with a post containing other form data

I have followed countless examples (from here and other sites) that explain how you upload files from Angular to a web server. I am happy with the solution of using angular-file-upload and processing the data on the server (Node) with Multer.
What I haven't been able to find is a way to upload files from the form with a post that contains all the other controller data.
controller:
$scope.files = [];
$scope.name = "";
$scope.post = //$http post to server from service
view:
<input type="text" ng-model="name">
<input type="file">
<button ng-click="post()">Send post without page refresh</button>
Is there a way I can send the [name] and the [files] in the same post? If I send with multi part data will that be ok for [name] and [files]? Do I need to send two separate posts?
At the moment, my working example submits with a form action of 'post' and an enctype of "multipart/form-data". But I don't want the page to refresh and I want to send [name] and [files] from the scope... do I need to attach the files from the form to the scope or get the scope to pull the files from the DOM?
You can push formData to file before upload.
$scope.uploader.onBeforeUploadItem = function(fileItem) {
fileItem.formData.push({name: $scope.name});
};
Please look through the demo for complete solution :)
Plunkr
<form>
<input type="text" placeholder="Enter Name here" ng-model="newCountry.Name" />
<label>Choose 1 or more files:</label>
<input type="file" ng-files="AddnewCountryFlag($files)" multiple />
<h3>Try Uploading Image file. It will preview your image.</h3>
<div ng-repeat="item in imagesrc">
<img src="{{item.Src}}" />
<label>{{item.Size}}kB</label>
</div>
<input type="submit" value="Send Data" ng-click="AddCountry()" />

Pass a picture from Angualrjs front-end to Laravel back-end

I'm building an app in which I need to upload an image with angularjs, pass it with other data to a save() method written in laravel, what is the simplest way to do it?
in my html I have a title field and an image uploader:
<form>
<input type="text" required ng-model="selectedAD.title">
<input type="file" name="file" ngf-max-size="2MB" required ng-model="selectedAD.image"/>
<a class="btn-portal" type="submit" ng-click="saveAD()">
</form>
and inside my js file, I pass these data into the save route which goes to the store() function in laravel and moves the image into a folder, like this:
$scope.selectedAD = ad;
$scope.saveAD = function(){
$scope.managementErrors = [];
adsResource.save($scope.selectedAD,function(success){
$('#ads-modal').modal('hide');
showSuccessAlert($scope,$timeout, getSuccessMessages(success),$('#successMessages'));
$scope.getAdsTimeout();
},function(error){
$scope.managementErrors = getErrorMessagesUpdate(error);
});
this way the image is not passed to laravel processing code, it instead passes null to the store function, any helpful guides ?

AngularJs: upload mutiple files from different sources

I am trying to upload two different files, an image and a pdf file, each from a different input as follows:
<div class="form-group" ng-class="libraries.error.img[0] ? 'has-error' : ''">
<label for="img">Image</label>
<input type="file" accept="image/*" ngf-select="" ngf-multiple="true" class="form-control" id="img" name="img" placeholder="Image" ng-model="libraries.library.img">
<p ng-if="libraries.error.img[0]" style="color: red">{{libraries.error.img[0]}}</p>
</div>
<div class="form-group" ng-class="libraries.error.document[0] ? 'has-error' : ''">
<label for="document">Document</label>
<input type="file" accept="application/pdf" ngf-select="" class="form-control" id="document" name="document" placeholder="Document" ng-model="libraries.library.document">
<p ng-if="libraries.error.document[0]" style="color: red">{{libraries.error.document[0]}}</p>
</div>
In the services file, I am sending it using the following:
store: function (library) {
console.log(library);
return Upload.upload({
url: 'api/libraries',
method: 'POST',
fields: {name: library.name, location: library.location},
file: [library.img, library.document]
});
},
But when I try to fetch the files at the server side as follows:
return $_FILES;
I keep getting:
[] No Properties
However when I change file to
file: library.img
meaning, I pass only one file, it works.
I am using ng-file-upload with AngularJS and the server side is Laravel
Any idea to solve this issue allowing both files to be sent to the server?!
I've had the same issue, and I was able to fix it by giving the JSON object for each file a different name (drawing inspiration from here). If I did not rename the objects, the server would receive the correct number of files but all of them would be identical. So if you were to apply this, your code would be:
store: function (library) {
console.log(library);
return Upload.upload({
url: 'api/libraries',
method: 'POST',
fields: {name: library.name, location: library.location},
file: [library.img, library.document]
fileFormDataName: [name1, name2]
});
},
I believe the names can be anything as long as they are unique. However, you now have to process the objects separately on your server side. I am not familiar with how you might do that in PHP, but on my Rails back-end, I can collect all of the files by their class:
files = params.values.find_all { |value| value.class == ActionDispatch::Http::UploadedFile }
Then I simply assign each file to the appropriate attribute of my model.

Resources