Reset file selection with single file upload with blueimp plugin and AngularJS - angularjs

My settings are as following:
singleFileUploads: false,
// To limit the number of files uploaded with one XHR request,
// set the following option to an integer greater than 0:
limitMultiFileUploads: undefined,
maxNumberOfFiles: 1,
I am trying to allow my client to upload a personal image, after successfully uploading this image,
I would like to reset the file selection, and allow my user to upload another image instead of the first one.
Before setting the maxNumberOfFiles setting to 1, the plugin just tried to upload any new file that the user would select along with the old ones, now, it allows the user to upload a file only once per each visit to the page which contains the plugin instance.
Here is what I've tried so far:
$scope.model.resetFiles = function(){
angular.forEach(
angular.element("input[type='file']"),
function(inputElem){
// angular.element(inputElem).val(null);
angular.element(inputElem).find('.files').empty();
angular.element(inputElem).scope().clear()
});
}

For security reasons, Javascript doesn't allow you to clear the file fields in the manner you'd think. It seems as if creating a new element and replacing the old file field will do the trick though. Check out this link for some more detail, and a code example.
I've seen some people suggesting wrapping the element in a <form> tag and using jQuery's reset() function to reset the form, but if you're not using the full version of jQuery, I don't believe this is included with the jqLite that's used by default by AngularJS.

I've found a temporary solution until the plugin gets updated for better Angular support.
var filePicker = null;
$scope.options = {
done: function (e, data) {
filePicker = data;
}
};
$scope.clearFiles = function () {
filePicker.scope.clear(filePicker.files);
};
Just add the options to the directive like this:
<form file-upload="options" action="import/excelupload" method="POST" enctype="multipart/form-data">

I simply solved it using this simple form reset
document.forms["mediaUploader"].reset();
my directive on the file input was autobinding the files to a scope variable.
after calling forms.reset(); also autobinds files.length to 0 zero so works marvelously!
also check out
https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement.reset

If file field is wrapped inside form tag then use standard html form reset button type.
<button type="reset" value="Reset">Reset</button>
Also you can put ng-click directive on reset button to perform any changes in $scope.
<button type="reset" value="Reset" ng-click="formReset()">Reset</button>
$scope.resetForm = function (){
// Your business logic after form reset.
}

Related

ng-change not working after first upload

http://embed.plnkr.co/keaGc3Y4Pmgfs04HJgnC/
Here is the link of my code.I am trying to validate my upload by disabling the load data button when the file is empty.
It is working for the first time,but when the next time I upload the file,ng-change is not working and the button is still showing disabled although I have uploaded the next file.
I am a beginner in AngularJS,so i might be doing some basic mistake.please help.
Since you are trying to upload the same file again, the onChange event will not fire, because it is the same file. To resolve this issue, you need to unset the input field after you uploaded the file. Unfortunately, you have to use jQuery (or get the element wit vanilla js) for this. So, in your onFileLoad function you could do something like this:
angular.element("input[type='file']").val(null); // Unset Input
$scope.filename = undefined; // Unset $scope property
Note that this is not the "angular" way of doing this. It would be better to move this into a directive, cause you should not manipulate the DOM within a Controller.
Update:
As said before, you need to include jQuery for this to work. Angular's jqLite does not support selecting DOM elements by its type. So, either you include jQuery (needs to be loaded before angular!) or you modify the code so you can use vanilla JS or jqlite.
Please change, initially
vm.foo = 'Monthly'
<input type="radio" name="{{item.deviceId}}" ng-model="renew.foo" ng-value="'Monthly'" ng-click="renew.updatePref(item, 'Monthly')">Monthly
<input type="radio" name="{{item.deviceId}}" ng-model="renew.bar" ng-value="'Yearly'" ng-click="renew.updatePref(item, 'Yearly')">Yearly
you have use ng-change, change event never happen as value for these input remains always same. use,
var vm = this;
you are also using ng-value="Monthly", Monthly is variable (undefiend) for ng-value. either use value="Monthly" or ng-value="'Monthly'".

Refresh image without changing ng-src

I have an image upload form which allows the user to upload a new profile picture. I need the image to refresh after a successful upload (with the same url in ng-src). I tried to append a random value to ng-src to force image reload using $scope.$apply but it's not working.
You don't need to use $scope.$apply, ng-src watches for changes so if you set a different value of what it was before it will change the image, check code and jsfiddle below:
https://jsfiddle.net/twizzlers/oebx8any/1/
$scope.current_src = "http://www.w3schools.com/css/trolltunga.jpg";
$scope.upload = function(){
//before upload
$scope.current_src = "test";
//after upload
$scope.current_src = "http://www.w3schools.com/css/trolltunga.jpg";
}
Hope it helps =)
I solved partially. I just added a function that delete the img dom and add it again (i know that's not the perfect solution but it works at all)

Angularjs form.$dirty

I'm able to find form data is changed or not using $dirty.
ex: I changed text box or drop down and then $dirty become true. If I reverted to old data still it is true. I need to know if my changes are reverted or not. Do we have any property in Angularjs? If property is true I want to enable save button otherwise it should be disable.
https://docs.angularjs.org/api/ng/type/form.FormController
I need to implement around 10 pages and each page has 10 text boxes and a couple of drop downs. So I don't want track each control manually in my pages.
You can try using this module: https://github.com/betsol/angular-input-modified
From the README file:
This Angular.js module adds additional properties and methods to the
ngModel and ngForm controllers, as well as CSS classes to the
underlying form elements to provide end-user with facilities to detect
and indicate changes in form data.
This extra functionality allows you to provide better usability with
forms. For example, you can add decorations to the form elements that
are actually changed. That way, user will see what values has changed
since last edit.
Also, you can reset an entire form or just a single field to it's
initial state (cancel all user edits) with just a single call to the
reset() method or lock new values (preserve new state) just by calling
overloaded $setPristine() method.
DISCLAIMER: I haven't tried it myself and I notice the author overwrites the ngModel directive instead of adding a decorator, which could be dangerous...but at the very least, you can look at the source and get an idea of how to write your own service or directive with similar functionality.
Even though it does not follow the usage of $dirty, but an implementation similar to this might be helpful for you in the case of a Save button on update.
Inside your html:
<form name="testForm" ng-controller="ExampleController" ng-submit=" save()">
<input ng-model="val" ng-change="change()"/>
<button ng-disabled="disableSave">Save</button>
</form>
Inside your controller:
.controller('ExampleController', ['$scope', function($scope) {
$scope.disableSave = true; // Keep save button disabled initially
$scope.val = 'Initial'; // Initial value of the variable
var copyVal = $scope.val; // Copy Initial value into a temp variable
$scope.change = function() {
$scope.disableSave = $scope.val === copyVal;
};
$scope.save = function() {
// Save the updated value (inside $scope.val)
console.log($scope.val);
// Re-disable the input box (on successful updation)
copyVal = $scope.val;
$scope.disableSave = true;
};
}]);
Here is a working plunkr for the same.

Adding cutom option to bootstrap modal

I am using bootstrap modals in my application.
In here we have modal options like windowClass, Keyboard, etc.
I want to know whether we can add our own custom options in here like 'preventModalClose', 'ABC', etc.
You need to modify the source code of bootstrap UI (I suppose you are using it because of the angularjs tag).
For example, go to the source file of modal.js. Go to Line 99, you will find that the option windowClass works simply by:
element.addClass(attrs.windowClass || '');
Say, you want to add a customized option like preventModalClose, just modify the function scope.close in Line 102:
scope.close = function (evt) {
if (attrs.preventModalClose) {
return;
}
// The original logic.
}
Start reading the source code of them, they are just Angular directives or even plain JavaScript.

Fine-Uploader How to capture additional params for each file while still allowing multiple files

I have the requirement to allow a user to select a file to upload and then need to capture additional required information from the user that applies to that specific file that will be sent as params to the server when uploading.
Thus far, I have been doing this by working off of the fine-uploader onSubmit callback and displaying a modal with the inputs I need. If inputs pass validation, I store the file id and associated params, otherwise, if they close/cancel the modal I call the fine-uploader cancel api and cancel the file with the given id.
The user can do this multiple times, which queues the files into the standard fine-uploader list and then they would press "Upload" to actually start the uploads concurrently.
All of this works great, my problem is that because I have the "multiple" option enabled, the user can select or drag multiple files at the same time, but I need to present the modal to each of them individually. The onSubmit event is firing individually for each of the files so how can I prevent the second, third, etc, modal from opening until I either cancel or save the previous one?
For the record I am actually using Backbone/Marionette and triggering a "file:added" event for each onSubmit callback. This is where I am creating the modal view and displaying it, however, the solution doesn't need to be tied to backbone.
Also, if there is a better way to collect parameters for a file using fine-uploader, I am not necessarily tied to this approach - just need to make sure that each file has the additional data populated otherwise it can not be uploaded.
Here is the Fine Uploader onSubmit callback:
.on('submit', function(event, id, name) {
var args = {};
args.id = id;
args.fileName = name;
uploadDocsVent.trigger('file:added', args);
})
Here is my code that is listening for that event, creating a File Backbone model, and instantiating a view to be displayed in a Modal region.
uploadDocsVent.on("file:added", function(args){
var file = new UploadDocuments.File( args );
var addlInfoView = new UploadDocuments.Views.FileInfo({
model: file,
categories: App.uploadedFilesCategories
});
App.appLayout.modalConfirmRegion.show(addlInfoView);
});
In my view I have this code responding to the modal clicks:
onDialogPrimaryClicked: function () {
UploadDocuments.claimsUploadWidget.addFileWithInfo( this.model );
this.trigger("dialog:close");
},
onDialogSecondaryClicked: function () {
UploadDocuments.uploadView.uploader.fineUploader('cancel', this.model.get('id'));
this.trigger("dialog:close");
}
Thanks in advance for any ideas on how to approach/get around this.
Andrew - I think I know what you are getting at. It's clear that you simply want Fine Uploader to only process a file in a batch of selected files after the user has submitted information in the modal that your display for that file in your onSubmit handler. What you are looking for is a way to return a promise, or a "deferred" in your onSubmit handler. This would allow you to call Fine Uploader back (and say "go ahead, upload/submit this file and move on to the next") once your user has submitted the associated modal.
I have already created a qq.Promise "class" that implements the promise pattern. Fine Uploader observes a promise as a valid return value only for the onPasteReceived callback at this time. It might make sense to allow this as a valid return value for other callbacks, such as onSubmit. This would allow you to defer uploading/submittal of a file until the user has dealt with the associated modal. Setting the multiple option to "false" may or may not be a desirable option for you now, due to the way Fine Uploader functions in "single-file mode".
I think it may be valuable to allow promises to be returned in some callbacks, such as this one, to allow for user interaction. Could you please open up a feature request in the Github project? There, we can discuss a bit more and you can track progress on any associated changes I put into the library.

Resources