Validating file extension in AngularJs before uploading - javascript

I am uploading images for our application to the server.
Is there any way to validate the extensions in client side by JS before submitting them to the server before uploading them to server?
I am using AngularJs to handle my front-end.

You can use this simple javascript to validate. This code should be put inside a directive and on change of file upload control.
var extn = filename.split(".").pop();
Alternatively you can use javascript substring method also:
fileName.substr(fileName.lastIndexOf('.')+1)

You can create a angular directive, something like this should work (Change the accepted values in the validFormats array);
HTML:
<form name='fileForm' >
<input type="file" name="file" ng-model="fileForm.file" validfile>
</form>
Javascript:
angular.module('appname').directive('validfile', function validFile() {
var validFormats = ['jpg', 'gif'];
return {
require: 'ngModel',
link: function (scope, elem, attrs, ctrl) {
ctrl.$validators.validFile = function() {
elem.on('change', function () {
var value = elem.val(),
ext = value.substring(value.lastIndexOf('.') + 1).toLowerCase();
return validFormats.indexOf(ext) !== -1;
});
};
}
};
});

for file validation i.e required,file extension,size.Create custom directive and used angular js ng-message module for simplify the validation errors
HTML
<input type="file" ng-model="imageFile" name="imageFile" valid-file required>
<div ng-messages="{FORMNAME}.imageFile.$error" ng-if="{FORMNAME}.imageFile.$touched">
<p ng-message="required">This field is required</p>
<p ng-message="extension">Invalid Image</p>
</div>
Angular JS
customApp.directive('validFile', function () {
return {
require: 'ngModel',
link: function (scope, elem, attrs, ngModel) {
var validFormats = ['jpg','jpeg','png'];
elem.bind('change', function () {
validImage(false);
scope.$apply(function () {
ngModel.$render();
});
});
ngModel.$render = function () {
ngModel.$setViewValue(elem.val());
};
function validImage(bool) {
ngModel.$setValidity('extension', bool);
}
ngModel.$parsers.push(function(value) {
var ext = value.substr(value.lastIndexOf('.')+1);
if(ext=='') return;
if(validFormats.indexOf(ext) == -1){
return value;
}
validImage(true);
return value;
});
}
};
});
Require
angular-messages.min.js

Here is the complete code for validating file extension usign AngularJs
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script type='text/javascript'>
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.setFile = function(element) {
$scope.$apply(function($scope) {
$scope.theFile = element.files[0];
$scope.FileMessage = '';
var filename = $scope.theFile.name;
console.log(filename.length)
var index = filename.lastIndexOf(".");
var strsubstring = filename.substring(index, filename.length);
if (strsubstring == '.pdf' || strsubstring == '.doc' || strsubstring == '.xls' || strsubstring == '.png' || strsubstring == '.jpeg' || strsubstring == '.png' || strsubstring == '.gif')
{
console.log('File Uploaded sucessfully');
}
else {
$scope.theFile = '';
$scope.FileMessage = 'please upload correct File Name, File extension should be .pdf, .doc or .xls';
}
});
};
});
</script>
</head>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
<input type="file"
onchange="angular.element(this).scope().setFile(this)">
{{theFile.name}}
{{FileMessage}}
</div>
</body>
</html>

You can add a custom directive which checks for the element.files array in order to check the type on the onchange event.
There is no embedded validation for file input.

File Upload using AngularJS
There are many modules that can help you with this. Any one of these should allow you to define a filter to only upload certain file extensions.
If you're looking for a simpler solution, you can use something like string.js to ensure the filenames of the files being uploaded are of extension '.png'.

Related

Attach $watch to input field in directive

The directive below is intended to take the value of the <input> tag and render the exact number of boxes. This directive needs to be restricted to E (bad design but is what it is), so it looks like I need to find some way of attaching a $watch to the input field.
Below you can see my best attempt, or at least a general sketch of what I'd like to accomplish, however this only triggers when the page originally loads. No change to the value in the input box is reflected by the alert statement.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="myApp">
<draw-boxes count="3"></draw-boxes>
<script>
var app = angular.module("myApp", []);
app.directive("drawBoxes", function() {
var input = "<input type='text'></input>";
var htmlCanvas = "<canvas width='800' height='800'></canvas>";
var template = input + htmlCanvas;
var linker = function(scope, el, attrs){
scope.$watch(el.children()[0], function (v) {
alert('value changed, new value is: ' + v);
//Will do some canvas drawing here based on input
});
};
return {
restrict: "E",
template : template,
link: linker
};
});
</script>
</body>
</html>
You can use ng-change on the input. Here is an example:
var app = angular.module("myApp", []);
app.directive("drawBoxes", function() {
var linker = function(scope, el, attrs){
scope.valueChanged = '';
scope.change = function() {
scope.valueChanged = 'new value is ' + scope.value;
};
};
return {
restrict: "E",
template : "<input type='text' ng-change=\"change()\" ng-model=\"value\"></input>"+
"<span>{{valueChanged}}</span>" +
"<canvas width='800' height='800'></canvas>",
link: linker
};
Here is a working example on jsfiddle.
Personally, I would try attaching a controller to the directive.
Also, the input field will need to have a unique ng-model value attached to it.
Then your $scope.$watch can check if the value has changed for the input field whenever any $scope value changes.
Something like this:
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="myApp">
<draw-boxes count="3"></draw-boxes>
<script>
var app = angular.module("myApp", []);
app.directive("drawBoxes", function() {
var input = "<input type='text' ng-model='watchedInput'></input>";
var htmlCanvas = "<canvas width='800' height='800'></canvas>";
var template = input + htmlCanvas;
return {
restrict: "E",
template : template,
controller: function($scope) {
$scope.$watch(function() {
// when a $scope value is changed, return the
// value you want this watcher to watch
return $scope.watchedInput;
}, function(newValue) {
// if the value returned above is different from the
// previous value, this function will be invoked
// passing in the changed value as newValue
alert('value changed, new value is: ' + newValue);
}, true);
},
scope: {},
bindToController: true
};
});
</script>
</body>
</html>
FYI: I haven't tested this code but wanted to illustrate the idea.

How to get the Local Storage data into the view file Using Angular js

Hello I am beginner in mean Stack. and I have data in localstorage and I want to fetch the data from the local storage and show in html file but I don't know How to get it. on the view file.
$scope.useredit = function (d) {
var user_id = d._id;
var dataToModify;
angular.forEach($scope.dp, function (value, key) {
if (user_id == value._id) {
dataToModify = value;
$localStorage.userData = dataToModify;
console.log($localStorage.userData.name);
$location.path('/useredit');
}
});
}
when I type localStorage; into console it show
ngStorage-userData
:
"{
"_id":"5846692617e0575c0e0c2211",
"password":123456,
"email":"montyy1981#gmail.com",
"name":"digvijay12","__v":0
}"
How to get it value into the view file.I used like
<div>{{userData.email}}</div>
But it is not showing data.please help me how to fetch localstorage data and show into view file.
You can use core concept without ngStorage....
https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage
localStorage.setItem("userData", $scope.Data);
$scope.storageData = localStorage.getItem("userData");
<p>{{storageData.email}}</p>
How to get the localStoragedata anywhere this is very simple we have to pass localStorage data into the controller global variable suppose
we have the data into localstorage
$scope.useredit = function (d) {
var user_id = d._id;
var dataToModify;
angular.forEach($scope.dp, function (value, key) {
if (user_id == value._id) {
dataToModify = value;
$localStorage.userData = dataToModify;
console.log($localStorage.userData.name);
$location.path('/useredit');
}
});
}
we have to define pass $localStorage.userData into the other variable after controller start.
app.controller("usercontroller",function($scope,$http, $localStorage,$location){
$scope.registeruser = $localStorage.userData;
$scope.useredit = function (d) {
var user_id = d._id;
var dataToModify;
angular.forEach($scope.dp, function (value, key) {
if (user_id == value._id) {
dataToModify = value;
$localStorage.userData = dataToModify;
console.log($localStorage.userData.name);
$location.path('/useredit');
}
});
}
});
For better understanding click this DEMO
In the controller you need to inject "ngStorage" angular.module('MyApp', ["ngStorage"]).
And add the dependency script link <script src="https://cdn.jsdelivr.net/ngstorage/0.3.6/ngStorage.min.js"></script>
HTML
<html ng-app="MyApp">
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.1/angular.min.js"></script>
<script src="https://cdn.jsdelivr.net/ngstorage/0.3.6/ngStorage.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="MyController">
<input type="button" value = "Save" ng-click = "Save()" />
<input type="button" value = "Get" ng-click = "Get()" />
</div>
</body>
</html>
Script.js
var app = angular.module('MyApp', ["ngStorage"])
app.controller('MyController', function ($scope, $localStorage, $sessionStorage, $window) {
$scope.Save = function () {
$localStorage.email = "xyz#gmail.com";
}
$scope.Get = function () {
$window.alert($localStorage.email);
}
});
Hope it will be usefull for you.

Angular components with javascript models and ngModel

I'm trying to create an angular component, a timepicker, using plain javascript models, I want the controller of the component expose an api and also working with ngModel.
I'm pretty newbie with angular and don't know how to work with ngModel. I have two inputs inside the template with hours and minutes. My problem is that I don't know how to pass the ngmodel parameters to the controller.
I've prepared a plunker:
http://plnkr.co/edit/aal3VP?p=preview
(function() {
var app = angular.module('plunker', []);
function DemoController() {
this.tpVal = {
hours: 10,
minutes: 0
};
}
app.controller('DemoController', DemoController);
function TimePickerModel(config) {
this.show = config.show || true;
this.hours = null;
this.minutes = null;
}
function TimePickerController() {
// API for state
this.model = new TimePickerModel({});
}
TimePickerController.prototype.show = function showTimePicker() {
this.model.show = true;
};
TimePickerController.prototype.hide = function hideTimePicker() {
this.model.show = false;
};
TimePickerController.prototype.setHours = function setHoursTimePicker(hours) {
this.model.hours = hours;
};
TimePickerController.prototype.setMinutes = function setMinutesTimePicker(minutes) {
this.model.minutes = minutes;
};
TimePickerController.prototype.setValue = function setValueTimePicker(value) {
this.model.hours = value;
this.model.minutes = value;
};
app.directive('timepicker', function($compile) {
return {
restrict: 'AE',
controller: 'TimePickerController',
scope: {},
require: 'ngModel',
templateUrl: 'timepicker.html',
link: function(scope, element, attrs, ngModel) {
//console.log('Model val: ' + ngModel.$modelValue);
//console.log('View val: ' + ngModel.$viewValue);
ngModel.$render = function() {
//Do something with your model
console.log(scope.model);
var actualValue = ngModel.$modelValue;
console.log('Model val: ' + ngModel.$modelValue.hours);
console.log('View val: ' + ngModel.$viewValue.hours);
//console.log(element.find('input')[0]);
//element.find('input')[0].val(actualValue.hours);
}
}
};
});
app.controller('TimePickerController', TimePickerController);
})();
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<script data-require="angular.js#1.4.7" data-semver="1.4.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<script data-require="angular.js#1.4.7" data-semver="1.4.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-route.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="app.js"></script>
</head>
<body>
<h1>Hello Plunker!</h1>
<div ng-controller="DemoController as ctrl">
{{ctrl.tpVal}}
<timepicker ng-model="ctrl.tpVal"></timepicker>
</div>
</body>
</html>
ng-model is a standard angular directive to bound inputs values to scope property, you don't need to inject it or call the directive property with the same name. If you want to inject the values from the controller into the directive, you can use scope property for that.
in directive:
scope: {
model : '=time'
},
in index.html
<timepicker time="ctrl.tpVal"></timepicker>
Check that modification: http://plnkr.co/edit/cJ0mjI?p=preview.
You also can see how changing model value inside the directive can propargate outside by adding dummy increaseHours function in directive;

Angular.js: Error: Module 'MyApp' is not available

I would like to use this plunk locally on my machine. However, when I either run it with the local Python server or http-server, I keep getting the following Error:
Uncaught Error: [$injector:modulerr] Failed to instantiate module myApp due to:
Error: [$injector:nomod] Module 'myApp' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
My html file looks like this:
<!DOCTYPE html>
<html ng-app="myApp">
<head lang="en">
<meta charset="utf-8" />
<title>Custom Plunker</title>
<script scr="main.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.1/papaparse.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-file-upload/1.1.5/angular-file-upload.min.js"></script>
<link rel="stylesheet" href="main.css">
</head>
<body ng-controller="MyCtrl">
<h1>CSV</h1>
<div>
<input type="checkbox" ng-model="append">
Append to existing on drag & drop
</div>
<div class="drop-container" nv-file-drop nv-file-over uploader="uploader">
<textarea ng-model="csv" placeholder="Enter your CSV here, or drag/drop a CSV file"></textarea>
</div>
<h1>D3 Flare JSON</h1>
<div>
<input type="checkbox" ng-model="compact"> Compact
</div>
<div>
<input type="text" ng-model="tags.parent" placeholder="parent tag">
<input type="text" ng-model="tags.children" placeholder="children tag">
<input type="text" ng-model="tags.leaf" placeholder="leaf tag">
<input type="text" ng-model="tags.size" placeholder="size tag">
</div>
<textarea readonly ng-model="json"></textarea>
</body>
</html>
And the main.js file looks like this:
CSV to D3 Flare JSON converter in AngularJSPreview Edit Code
index.html
main.js
main.css
main.js
angular.module('myApp', ['angularFileUpload'])
.factory('FlareJson', ['$q', function($q) {
function updateTree(curr, arr, tags) {
if ((arr.length || 0) < 2) {
return;
}
if (!curr.hasOwnProperty(tags.children)) {
curr[tags.children] = [];
}
var elem;
if (arr.length == 2) {
elem = {};
elem[tags.leaf] = arr[0];
elem[tags.size] = arr[1];
curr[tags.children].push(elem);
} else {
curr[tags.children].some(function(e) {
if (e[tags.parent] == arr[0] || e[tags.leaf] == arr[0]) {
elem = e;
return true;
}
});
if (!elem) {
elem = {};
elem[tags.parent] = arr[0];
curr[tags.children].push(elem);
}
updateTree(elem, arr.slice(1), tags);
}
}
function buildJson(csv, compact, tags) {
var deferred = $q.defer();
var result = {};
result[tags.parent] = 'flare';
Papa.parse(csv, {
header: false,
dynamicTyping: true,
complete: function(csvArray) {
csvArray.data.forEach(function(line) {
if (line.length) {
updateTree(result, line, tags);
}
});
if (compact) {
deferred.resolve(JSON.stringify(result));
} else {
deferred.resolve(JSON.stringify(result, null, 2));
}
}
});
return deferred.promise;
}
return buildJson;
}])
.controller('MyCtrl', ['$scope', 'FileUploader', 'FlareJson',
function($scope, FileUploader, FlareJson) {
$scope.csv = "";
$scope.compact = false;
$scope.json = "";
$scope.tags = {
parent: 'skill',
children: 'children',
leaf: 'name',
size: 'level'
};
$scope.uploader = new FileUploader();
$scope.uploader.onAfterAddingFile = function(fileItem) {
var reader = new FileReader();
reader.onloadend = function(event) {
$scope.$apply(function() {
if ($scope.append) {
$scope.csv += event.target.result;
} else {
$scope.csv = event.target.result;
}
});
};
reader.readAsText(fileItem._file);
};
function update() {
FlareJson($scope.csv, $scope.compact, $scope.tags).then(function(json) {
$scope.json = json;
});
}
$scope.$watchGroup(['csv', 'compact'], update);
$scope.$watchCollection('tags', update);
}]);
I don't understand what I'm doing wrong. I already searched for similar error messages, but nothing that I found could help me to solve my problem.
You load your script file before angularjs file that's why you are getting this error.
So, Add your "main.js" file after "angular.js" file.
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>
<script scr="main.js"></script>
I believe it's because you're loading your main.js before you load Angular. Try putting your script at the end of the script definitions:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.1/papaparse.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-file-upload/1.1.5/angular-file-upload.min.js"></script>
<script scr="main.js"></script>
Oh, solved! Turns out, that the following couple of first lines in main.js were causing the trouble:
CSV to D3 Flare JSON converter in AngularJSPreview Edit Code
index.html
main.js
main.css
main.js
I removed them from main.js, now it works - yuhuu! :)

A validation directive that reacts to another value works in 1.0.x but not in 1.2.x

In angular js, I want to create a validator that will cause the ng-model value to become invalid when another value is specified. Now I have something that works fine for angular js 1.1.4 (which I was using because I was using an old plunkr), but when I switch to 1.1.5, it stops working.
I am sure I am doing something wrong with the scope, but I am not sure what.
Here is my code (plunkr here: http://plnkr.co/edit/Ug9oM1LNqPpTsONhRTnG?p=preview)
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope) {
$scope.doSomething = function () {
alert('Submitted!');
}
$scope.data = {};
$scope.data.value = new String('blah');
$scope.data.value.$$error = 'My Error';
$scope.data.toggleError = function() {
if ($scope.data.value.$$error) {
$scope.data.value.$$error = null;
}
else {
$scope.data.value.$$error = "SOME ERROR";
}
};
console.log($scope.data.value instanceof String);
});
app.directive('serverError', function (){
return {
require: 'ngModel',
scope:true,
link: function(scope, elem, attr, ngModel) {
scope.$watch('attr.errorValue', function() {
console.log("The error value is " + scope.errorValue);
ngModel.$setValidity('serverError', scope.errorValue == null);
});
}
};
});
Here is my HTML:-
<!DOCTYPE html>
<html ng-app="angularjs-starter">
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.3/angular.min.js"></script>
<link rel="stylesheet" href="style.css">
<script>
document.write('<base href="' + document.location + '" />');
</script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<form name="myForm" ng-submit="doSomething()">
<input type="text" name="fruitName" ng-model="data.value" serverError errorValue="data.value.$$error" />
<div>{{ data.value.$$error }}</div>
<span class="invalid" ng-if="myForm.fruitName.$error.serverError">
{{data.value.$$error}}
</span>
<br/>
<button type="submit" ng-disabled="myForm.$invalid">Submit</button>
<input type="button" ng-click="data.toggleError()" value="Toggle Error"/>
</form>
</body>
</html>
As soon as I change from 1.1.3 to 1.2.0, my directive stops working.
I worked it out.
http://plnkr.co/edit/Ug9oM1LNqPpTsONhRTnG?p=preview
The directive is simple enough:-
app.directive('serverError', function($parse) {
return {
// restrict to an attribute type.
restrict: 'A',
// element must have ng-model attribute.
require: 'ngModel',
// scope = the parent scope
// elem = the element the directive is on
// attr = a dictionary of attributes on the element
// ctrl = the controller for ngModel.
link: function(scope, elem, attr, ctrl) {
scope.$watch(attr.serverError, function(newValue, oldValue) {
if (newValue != null) {
ctrl.$setValidity('serverError', false);
}
else {
ctrl.$setValidity('serverError', true);
}
});
}
};
});

Categories

Resources