AngularJS Image Preview before Upload showing previous image selected - javascript

myApp.directive('fileModel', ['$parse', function($parse) {
return {
restrict: 'A',
link: function($scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(e) {
$scope.$apply(function(e) {
modelSetter($scope, element[0].files[0]);
});
$scope.setimage();
});
}
The above code is my directive.
In the function $scope.setimage()
$scope.setimage = function() {
var file = $scope.myFile;
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e) {
$scope.ImageSrc = e.target.result;
}
}
Whenever i choose the file,
<img width= 250 height=350 ng-src="{{ImageSrc}}"/>
<input type=`enter code here`"file" file-model="myFile"/>
Immediately the preview is not appearing. When i choose the second time, the preview for the previously selected image file is appearing. Not sure what is wrong.

Instead of element.bind('change', ..., you can use $scope.$watch on myFile, like so:
$scope.$watch('$scope.myFile', function(e) {
$scope.$apply(function(e) {
modelSetter($scope, element[0].files[0]);
});
$scope.setimage();
});
Note that $scope.myFile needs to be defined for this to occur, so if it's not defined in your directive you'll need to add this to your controller instead.

I added $scope.$apply for the imagesrc assignment and the image updated immediately.
$scope.setimage = function() {
var file = $scope.myFile;
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e) {
$scope.$apply(function(){
$scope.ImageSrc = e.target.result;
}); }
}

Related

Controller's properties does not change dynamic

.controller('ImageChangeController', function($scope, $http, $element){
$scope.itemid = '';
reader = new FileReader();
file_inputs = $element.children('.img-change');
img_doc = $element.children('img').get(0);
file_inputs.change(function(e){
reader.onload = function(e) {
img_doc.src = e.target.result;
}
$scope.itemid = "999"; //does not work
});
$scope.change_name = function(){
$scope.itemid = "999";
}
here is my template code:
<div ng-controller="ImageChangeController">
<span>{{itemid}}</span>
<input type="file" class="img-change" name="{{itemid}}" accept="image/*">
</div>
if I change itemid through ng-click="change_itemid()", it will be work well.
Basically, you should use angular directives instead of non-native elements:
http://ngmodules.org/modules/ng-file-upload
If you want to solve problem without changing the implementation (for example, the direcitve does not give you feature you want):
The problem source is this part of code:
file_inputs.change(function(e){
reader.onload = function(e) {
img_doc.src = e.target.result;
}
$scope.itemid = "999"; //does not work
});
the function is called outside the angular digest cycle. You should inform angular about changes:
file_inputs.change(function(e){
reader.onload = function(e) {
img_doc.src = e.target.result;
$scope.$applyAsync();
}
$scope.itemid = "999"; //does not work
$scope.$applyAsync();
});

How Display Image on page After $on("fileSelected") in angular js

How can I display an image after $on("fileSelected") in AngularJS?
I'm selecting a file using the following:
$scope.$on("fileSelected", function (event, args) {
debugger;
$scope.$apply(function () {
$scope.file = args.file;
});
I need to display the image with the img src attribute.
Try something like this:
var reader = new FileReader();
reader.onload = function (e) {
$('#image').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);

FileReader() is not defined in Angularjs Directive

I am working on file upload functionality on UI. Basically, on my UI page, I need to read file contents and display when the user selects local file from his/her machine. For this, I googled and I found this http://plnkr.co/edit/eeQbR65oE8iljm7ueGhX?p=preview example. It is working fine. but I used in my application, its not working and giving me error that"FileReader" is not defined.
Here is my example:
function onReadFile($parse) {
return {
restrict: 'A',
scope: false,
link: function(scope, element, attrs) {
var fn = $parse(attrs.onReadFile);
element.on('change', function(onChangeEvent) {
var reader = new FileReader();
reader.onload = function(onLoadEvent) {
scope.$apply(function() {
fn(scope, {$fileContent:onLoadEvent.target.result});
});
};
reader.readAsText((onChangeEvent.srcElement || onChangeEvent.target).files[0]);
});
}
};
}

img ng-src : TypeError: Converting circular structure to JSON

I have to get a picture in a modal just after its upload. So I'm opening a modal ($scope.openResizeModal()), and putting my picture in my scope.
uploads.client.controller.js
$scope.openResizeModal = function (flow) {
$scope.pictureToCrop = {};
$scope.pictureToCrop = flow.files[0];
}
Then I try to print in on my HTML view :
resize-modal.client.view.html
<img-cropped src="{{pictureToCrop}}" selected='selected(cords)'></img-cropped>
And AngularJS tells :
Error: [$interpolate:interr] Can't interpolate: {{pictureToCrop}}
TypeError: Converting circular structure to JSON
I even tried with a classic
<img src={{pictureToCrop}} />
But it's the same.
Here is my directive :
angular.module('uploads').directive('imgCropped', function () {
return {
restrict: 'E',
replace: true,
scope: { src: '#', selected: '&' },
link: function (scope, element, attr) {
var myImg;
var clear = function () {
if (myImg) {
myImg.next().remove();
myImg.remove();
myImg = undefined;
}
};
scope.$watch('src', function (nv) {
clear();
if (nv) {
element.after('<img />');
myImg = element.next();
myImg.attr('src', nv);
$(myImg).Jcrop({
trackDocument: true,
onSelect: function (x) {
scope.$apply(function () {
scope.selected({ cords: x });
});
},
aspectRatio: 1/1.4
}, function () {
// Use the API to get the real image size
var bounds = this.getBounds();
pwGlobal.boundx = bounds[0];
pwGlobal.boundy = bounds[1];
});
}
});
scope.$on('$destroy', clear);
}
};
});
Thanks all !
It was a flow internal problem :
var fileReader = new FileReader();
fileReader.readAsDataURL(flow.files[0].file);
fileReader.onload = function (event) {
$scope.pictureToCrop = event.target.result;
};
Solved my problem. The image is converted in base64 encode.

How to read a file in AngularJS?

Is it possible to read files in AngularJS? I want to place the file into an HTML5 canvas to crop.
I was thinking of using a directive? This is the javascript code I want to put into my directive:
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#blah').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
Yes, directives is a right way, but it looks little bit different:
.directive("ngFileSelect",function(){
return {
link: function($scope,el){
el.bind("change", function(e){
$scope.file = (e.srcElement || e.target).files[0];
$scope.getFile();
});
}
}
})
Working example: http://plnkr.co/edit/y5n16v?p=preview
Thanks to lalalalalmbda for this link.
I've taken Cherniv's code and folded all of it into a directive:
.directive('fileSelect', ['$window', function ($window) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, el, attr, ctrl) {
var fileReader = new $window.FileReader();
fileReader.onload = function () {
ctrl.$setViewValue(fileReader.result);
if ('fileLoaded' in attr) {
scope.$eval(attr['fileLoaded']);
}
};
fileReader.onprogress = function (event) {
if ('fileProgress' in attr) {
scope.$eval(attr['fileProgress'],
{'$total': event.total, '$loaded': event.loaded});
}
};
fileReader.onerror = function () {
if ('fileError' in attr) {
scope.$eval(attr['fileError'],
{'$error': fileReader.error});
}
};
var fileType = attr['fileSelect'];
el.bind('change', function (e) {
var fileName = e.target.files[0];
if (fileType === '' || fileType === 'text') {
fileReader.readAsText(fileName);
} else if (fileType === 'data') {
fileReader.readAsDataURL(fileName);
}
});
}
};
}]);
You can then use the directive as follows:
<input type="file" ng-model="file.data"
file-select="data"
file-loaded="myLoaded()"
file-error="myError($error)"
file-progress="myProgress($total,$loaded)">
Where "file.data", "myLoaded", "myError", and "myProgress" are in the enclosing scope.
Angular File reader.
link: function(scope, element, attrs) {
element.on('change', function(e) {
var reader = new FileReader();
reader.onload = function(e) {
scope.$apply(function() {
scope.onReadFile({$content:e.target.result});
});
};
reader.readAsText((e.srcElement || e.target).files[0]);
});
}
Live example : Live Run On Plunker

Categories