AngularJS - upload and display image using FileReader API (multiple files) [duplicate] - angularjs

This question already has answers here:
Directive to get files input with ng-model [duplicate]
(1 answer)
ng-model for `<input type="file"/>` (with directive DEMO)
(13 answers)
Closed 5 years ago.
I use the following example, it works perfectly , but I'd like to upload multiple images simultaneously.
http://jsfiddle.net/kkhxsgLu/2/
<div ng-controller="MyCtrl">
<div ng-repeat="step in stepsModel">
<img class="thumb" ng-src="{{step}}" />
</div>
<input type='file' ng-model-instant onchange="angular.element(this).scope().imageUpload(this)" />
$scope.stepsModel = [];
$scope.imageUpload = function(element){
var reader = new FileReader();
reader.onload = $scope.imageIsLoaded;
reader.readAsDataURL(element.files[0]);
}
$scope.imageIsLoaded = function(e){
$scope.$apply(function() {
$scope.stepsModel.push(e.target.result);
});
}
Thank you kindly help me, I started with angularjs

SOLUTION:
http://jsfiddle.net/orion514/kkhxsgLu/136/
:)
<div ng-controller="MyCtrl">
<div ng-repeat="step in stepsModel">
<img class="thumb" ng-src="{{step}}" />
</div>
<input type='file' ng-model-instant
onchange="angular.element(this).scope().imageUpload(event)"
multiple />
$scope.stepsModel = [];
$scope.imageUpload = function(event){
var files = event.target.files; //FileList object
for (var i = 0; i < files.length; i++) {
var file = files[i];
var reader = new FileReader();
reader.onload = $scope.imageIsLoaded;
reader.readAsDataURL(file);
}
}
$scope.imageIsLoaded = function(e){
$scope.$apply(function() {
$scope.stepsModel.push(e.target.result);
});
}

Directive to get files input with ng-model (multiple files)
The AngularJS built-in <input> directive does not handle <input type=file>. One needs a custom directive for that.
<input type="file" files-input ng-model="fileArray" multiple>
The files-input directive:
angular.module("app").directive("filesInput", function() {
return {
require: "ngModel",
link: function postLink(scope,elem,attrs,ngModel) {
elem.on("change", function(e) {
var files = elem[0].files;
ngModel.$setViewValue(files);
})
}
}
})
The above directive adds a change listener that updates the model with the files property of the input element.
This directive enables <input type=file> to automatically work with the ng-change and ng-form directives.
The DEMO on PLNKR
Inline Demo of files-input Directive
angular.module("app",[]);
angular.module("app").directive("filesInput", function() {
return {
require: "ngModel",
link: function postLink(scope,elem,attrs,ngModel) {
elem.on("change", function(e) {
var files = elem[0].files;
ngModel.$setViewValue(files);
})
}
}
});
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
<h1>AngularJS Input `type=file` Demo</h1>
<input type="file" files-input ng-model="fileArray" multiple>
<h2>Files</h2>
<div ng-repeat="file in fileArray">
{{file.name}}
</div>
</body>

Zypps987, try using var file = files[0], not inside a loop.

Related

How to trigger element click on angular js?

I have an input file and it is hidden. I want to trigger the input file once the button is clicked but my code is not working. What changes does it need to make it work?
HTML:
<input type="file" ng-model="data.file" id="upload" style="display:none;">
<button type="button" ng-click="browseFile()">Choose a file</button>
JavaScript:
$scope.browseFile = function () {
angular.element(document.querySelector('#upload')).triggerHandler('click');
}
In html use something like below
<img id="preview_image" src="" accept="image/*" class="upload_img" alt="">
<input id="image_upload" ng-model="file" type="file" class="upload_image_file" />
And in controller use $watch
$scope.$watch("file", function() {
readURL(angular.element("#image_upload")[0]);
});
function readURL(input) {
if (input && input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
angular.element("#preview_image").attr("src", e.target.result);
vm.base64File = e.target.result;
};
reader.readAsDataURL(input.files[0]);
}
}
For more info, read here and here
Update
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.file = '';
$scope.$watch("file", function() {
console.log($scope.file)
});
});
app.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() {
scope.$apply(function() {
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<label class="upload_image_label" for="image_upload">
choose file
<input id="image_upload" file-model="file" type="file" style="display:none" />
</label>
<hr> <br> File: {{file}}
</div>
</body>
</html>
As adardesign said
This is due to a security restriction.
I found out that the security restriction is only when the
<input type="file"/>
is set to display:none; or is visibility:hidden.
So i tried positioning it outside the viewport by setting
position:absolute and top:-100px; and voilà it works.
You can find more in this post: Jquery trigger file input

How can I Upload two files using two different file input in Angular Js?

I am checking extension of files , using angular js , my html code is:
<input type="file" name="file" onchange=" angular.element(this).scope().selectFileforUpload(this.files) " required/>
<input type="button" value="Click" ng-click="click()" />
and angular controller code is :
$scope.verifiedFileType = function (file) {
var fileName = file.name;
var extension = (fileName.substring(fileName.lastIndexOf('.'), fileName.length)).toLowerCase();
if (extension === ".pdf") {
return true;
}
else {
return false;
}
};
$scope.click = function () {
if ($scope.verifiedFileType($scope.SelectedFileForUpload)) {
alert("Yes");
} else {
alert("No");
}
}
This works fine. But I want to check the extension of two files of two separete file inputs. I have tried this:
<input type="file" name="file" onchange=" angular.element(this).scope().selectFileforUpload(this.files) " required/>
<input type="file" name="file2" onchange=" angular.element(this).scope().selectFileforUpload(this.files) " required/>
<input type="button" value="Click" ng-click="click()" />
$scope.click = function () {
if ($scope.verifiedFileType($scope.SelectedFileForUpload[0]) && $scope.verifiedFileType($scope.SelectedFileForUpload[1])) {
alert("Yes");
} else {
alert("No");
}
}
But this code doesn't run. How can I perfom this task?
You can try below-given directive approach to achieve this.
Directive
app.directive('ngFileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var validFormats = ['jpg'];
element.bind('change', function () {
var values = [];
angular.forEach(element[0].files, function (item) {
var fileName = item.name;
console.log(fileName);
let ext = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
if(validFormats.indexOf(ext) == -1){
//Setup image upload logic here...
}
});
});
}
};
}]);
HTML
<body ng-controller="MainCtrl">
<input type="file" ng-file-model="files1" multiple />
<input type="file" ng-file-model="files" multiple />
</body>
Hope this will give you boost!

Disable and empty model value and then restore it

I have working code:
<input type="checkbox" ng-model="disabled" >
<input type="text" ng-model="text" ng-disabled="disabled">
When disabled == true the input is disabled. I need to hide actual model value (set empty) as well. And after uncheck the checkbox actual model value should appears. How to do it without changing model value?
I would do something like this:
<input type="checkbox" ng-model="disabled" ng-change="change()">
<input type="text" ng-model="text" ng-disabled="disabled">
...
$scope.change = function() {
if ($scope.disabled) {
$scope.textBackup = $scope.text;
$scope.text = '';
} else {
$scope.text = $scope.textBackup;
}
};
Note: I posted before reading #AbdulMateenMohammed comment... My answer is an implementation of his suggestion...
This is not the best option but if you want to deal only with the view:
<input type="checkbox" ng-model="disabled">
<div ng-show="disabled">
<input type="text" ng-init="text2 = ''" ng-model="text2" ng-disabled="true">
</div>
<div ng-hide="disabled">
<input type="text" ng-model="text">
</div>
Again, this is not the best option!!! MarcosS option is the recommended.
#Makarov Sergey, I think even when you have a complex view or data source the basic idea is to use a temporary variable because you need to have two values b/w which you swap around.
angular
.module('demo', [])
.controller('DefaultController', DefaultController);
function DefaultController() {
var originalText = '';
var vm = this;
vm.text = 'Hello, World!';
vm.onValueChanged = onValueChanged;
function onValueChanged(text) {
if (vm.disabled) {
originalText = text;
vm.text = '';
} else {
vm.text = originalText;
}
}
}
span {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div>
<em>I </em><span>♥ </span><em>AngularJS</em>
</div>
<div ng-app="demo">
<div ng-controller="DefaultController as ctrl">
<input type="checkbox" ng-model="ctrl.disabled" ng-change="ctrl.onValueChanged(ctrl.text)"/>
<input type="text" ng-model="ctrl.text" ng-disabled="ctrl.disabled"/>
</div>
</div>
Tip: For the objects that aren't displayed in the view but present in the controller shouldn't be assigned on the scope because using scope would add some JavaScript events to do the data-binding which is unnecessary overhead such as the dirty check event for the two-way data-binding so that's why in the sample code snippet I used var originalText = ''; instead of vm.originalText = '';
Found the solution that works for me atm
function directive() {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
let oldViewValue = '';
scope.$watch(() => attrs.hideValue, (newV) => {
if (newV == 'true') {
oldViewValue = ngModelCtrl.$viewValue;
ngModelCtrl.$viewValue = '';
} else {
ngModelCtrl.$viewValue = oldViewValue;
}
ngModelCtrl.$render();
});
}
}
}
And use:
<input type="checkbox" ng-model="disabled" >
<input type="text" ng-model="text" ng-disabled="disabled" hide-value="disabled">

angularjs upload file using components

I am trying to upload file using angular component structure but i am not able to get the selected files.
Step 1:Template data.
<form name="form">
Hello {{vm.name}} <br />
Upload: <input my-directive type="file" name="file" ng-model="files" /> <br />
<input type="button" ng-click='vm.uploadFile()' value="Upload File." />
</form>
Step 2: Js file combined looks like
'use strict';
angular.module('app', ['ngFileUpload']);
class TestController {
constructor(){
this.name = 'user';
}
getFiles(selectedFiles){
console.log('Selected files are : ' + JSON.stringify(selectedFiles));
this.files = selectedFiles; // results empty data.
}
uploadFile (){
console.log('Model data i.e. files consists of : ' + JSON.stringify(this.files));
// Upload code will do later.
}
}
angular.module('app').directive('myDirective', function () {
return {
restrict: 'A',
scope: true,
link: function (scope, element, attr) {
element.bind('change', function () {
console.log('Value of element is :' + JSON.stringify(element[0].files[0]));
});
}
};
});
//Created a test controller here.
angular.module('app').controller('TestController', TestController);
// Created a component here.
angular.module('app').component('test', {
templateUrl: 'test.html',
controller: TestController,
controllerAs : 'vm',
});
Thanks in Advance, well i am new to angular :)
Sorry, I didn't notice that you were using typescript. I'm not really up to speed on ts at all yet. I answered a somewhat similar question that I can't find right now the other day with the code below. Note that there's an issue with ng-model and the file input type, so it uses document.getElementById to figure out the file. I suspect that this issue is what you're running into.
<html>
<body>
<form name="form" ng-app="app" ng-controller="Ctrl as ctrl">
Upload file:
<input type="file" id="file" ng-model="ctrl.file" />
<br/>
<br/> Enter text:
<textarea id="textarea" ng-model="ctrl.text"></textarea>
<br/>
<br/>
<button class="btn btn-primary btn-large" ng-click="ctrl.submitForm()">Submit</button>
</form>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js">
</script>
<script>
angular.module('app', []).controller('Ctrl', function() {
var vm = this;
vm.file = ""
vm.text = ""
vm.submitForm = function() {
// angular doesn't update the model for input type="file"
vm.file = document.getElementById('file').value;
var retVal = false ;
alert(vm.file);
alert(vm.text);
if (vm.file && ! vm.text)
{retVal = true}
else if (vm.text && ! vm.file)
{retVal = true}
else if (!vm.text && !vm.file)
{retVal = false}
else if (vm.text && vm.file)
{retVal = false}
if (!retVal) {
alert("Please specify either a file or text, not both!")
} else
alert("ok")
}
});
</script>
</html>

Angular highlight/select all content inside <div> element Angular

How do we highlight and select all content inside a element on click using Angular JS ?.
It is easy to do using inputbox. But how do we do for element.
Help would be appreciated.
Thank you
This is what I have used so far.
HTML
<div ng-controller="appController" ng-app="app">
<input type="text" ng-model="content" ng-click="onTextClick($event)" />
</div>
JS
var app = angular.module('app', []);
app.controller('appController',
function ($scope) {
$scope.content = 'test';
$scope.onTextClick = function ($event) {
$event.target.select();
};
});
http://jsfiddle.net/onury/R63u5/
jsfiddle: http://jsfiddle.net/n63LhtcL/3/
Here is an updated directive to achieve it:
.directive('selectOnClick', function ($window) {
return {
link: function (scope, element) {
element.on('click', function () {
var selection = $window.getSelection();
var range = document.createRange();
range.selectNodeContents(element[0]);
selection.removeAllRanges();
selection.addRange(range);
});
}
}
});
Your markup:
<div select-on-click>
Some text...
<input type="text" ng-model="content" />
</div>

Resources