Image upload, acquire image dimensions in directive - angularjs

I have following angular-js directive to 'upload' local Images:
app.directive('ngFileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var model = $parse(attrs.ngFileModel);
var isMultiple = attrs.multiple;
var modelSetter = model.assign;
element.bind('change', function () {
var values = [];
angular.forEach(element[0].files, function (item) {
var value = {
// File Name
name: item.name,
//File Size
size: item.size,
//File URL to view
url: (URL || webkitURL).createObjectURL(item),
// File Input Value
_file: item
};
values.push(value);
});
scope.$apply(function () {
if (isMultiple) {
modelSetter(scope, values);
} else {
modelSetter(scope, values[0]);
}
});
});
}
};
}]);
I now want to acquire the image-dimensions, but I don't know how.
I tried something like that (below the line values.push(value)):
var img = new Image();
img.src = value.url;
alert("Width: " + img.width);
but that didn't work. I also tried with img.onload, but I coudn't get a result either.
How can I acquire the image-dimensions?
Thanks!

Solved it by myself, image.onload was the right way to go:
app.directive('ngFileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var model = $parse(attrs.ngFileModel);
var isMultiple = attrs.multiple;
var modelSetter = model.assign;
element.bind('change', function () {
var values = [];
angular.forEach(element[0].files, function (item) {
var img = new Image();
var imgheight = 0;
var imgwidth = 0;
var imgurl = (URL || webkitURL).createObjectURL(item);
img.src = imgurl;
img.onload = function() {
imgheight = img.height;
imgwidth = img.width;
//alert("Width: " + imgheight + " height: " + imgwidth);
var value = {
// File Name
name: item.name,
//File Size
size: item.size,
//File URL to view
url: imgurl,
// File Input Value
_file: item,
width: imgwidth,
height: imgheight,
mystyle: {}
};
scope.$apply(function () {
values.push(value);
});
};
});
scope.$apply(function () {
if (isMultiple) {
modelSetter(scope, values);
} else {
modelSetter(scope, values[0]);
}
});
});
}
};
}]);

Related

FileReader() onload function not firing

I know this is a duplicate but none of the answers have helped so far..
I have this directive:
app.directive('fileReader', function () {
return {
scope: {
fileReader: "="
},
link: function (scope, element) {
$(element).on('change', function (changeEvent) {
var files = changeEvent.target.files;
if (files.length) {
var reader = new FileReader();
console.log('reader created');
reader.onload = function (e) {
console.log('onload hit');
};
}
});
}
};
})
And this DOM element linked to the directive:
<input type="file" id="file" file-reader="fileContent"/>
When I select a file for my input, my console prints out reader created, but never prints onload hit. I can not figure out how to properly fire off my onload function. What am I doing wrong here?
### Directive ###
app.directive('fileReader', ['$rootScope', function($rootScope) {
return {
scope: {
fileReader:"="
},
link: function(scope, element) {
$(element).on('change', function(changeEvent) {
var files = changeEvent.target.files;
if (files.length) {
$rootScope.uploadedFileName = files[0].name;
var r = new FileReader();
r.onload = function(e) {
var contents = e.target.result;
scope.$apply(function () {
scope.fileReader = contents;
$rootScope.uploadedFileName = files[0].name;
});
};
r.readAsText(files[0]);
}
});
}
};
}]);
### HTML ###
<input type="file" accept=".csv" id="myFile" file-reader="fileContent"/>

AngularJS directive is not updating template if controller name is not attached

If I specify the controller property in the code below then my code will work. Otherwise the code is not updating the HTML template:
function ngVisualizer($http, $timeout, SharedFactory, ThreejsFactory) {
return {
restrict: 'A',
template: '<div id="canvas"></div>',
transclude: 'true',
priority: Number.MIN_SAFE_INTEGER, //Lowest priority
link: function (scope, elem, attr, ctrl) {
angular.element(document).ready(function () {
var log = [];
// play audio sound.
var audio = new Audio('/Audio/Om_Sound.mp3');
audio.loop = true;
//audio.play();
scope.$watch("fileData", function (newValue, oldValue) {
if (SharedFactory.getRefreshStatus()) {
scope.RemoveEntity();
scope.dateTime = 0;
debugger;
console.log(scope.fileData);
//ESTS service and service name created and added to scene.
var planetSize = scope.centralPlanetSize(scope.countOfMachines);
var centralPlanet = scope.drawCentralPlanet(planetSize, scope.getColor(scope.planetPressure, 100));
var centralPlanetText = scope.draw2DText(scope.sliceName, scope.destinationPoint, planetSize);
scope.sceneObject.add(centralPlanet);
scope.sceneObject.add(centralPlanetText);
//scope.nwScene.add(centralPlanet);
//scope.nwScene.add(centralPlanetText);
//scope.central = null;
angular.forEach(scope.fileData, function (value, key) {
try {
var sphere = new THREE.Mesh(scope.outerGeometry, scope.outerMaterial);
//line creation among services
var sourcePoint = new THREE.Vector3(scope.destinationPoint.x, scope.destinationPoint.y, scope.destinationPoint.z);
var destinationPoint = new THREE.Vector3(ThreejsFactory.getPlanetList()[key].x, ThreejsFactory.getPlanetList()[key].y, ThreejsFactory.getPlanetList()[key].z);
//var path = new THREE.LineCurve3(sourcePoint, destinationPoint);
var path = scope.getCurvePath(sourcePoint, destinationPoint);
//var hexColorValue = scope.getHexColorValue(value.MaxCount);
var tube = scope.drawPipe(path, scope.getColor(value.MaxCount, 65000));
//text for service name
var serviceTextGeometry = scope.draw2DText(value.ServiceName , ThreejsFactory.getPlanetList()[key], 40);
//scope.nwScene.add(serviceTextGeometry);
scope.sceneObject.add(serviceTextGeometry);
//sphere for service name
sphere.position.set(ThreejsFactory.getPlanetList()[key].x, ThreejsFactory.getPlanetList()[key].y, ThreejsFactory.getPlanetList()[key].z);
//scope.nwScene.add(tube);
scope.sceneObject.add(tube);
//scope.nwScene.add(sphere);
scope.sceneObject.add(sphere);
//from ests
var toChild = scope.drawTorusIn(tube.geometry.parameters.path.v2, scope.pipeWidth, scope.getDonutFatness(value.DataBytesIn), "red");
//scope.nwScene.add(toChild);
scope.sceneObject.add(toChild);
//to ests
var toParent = scope.drawTorusOut(tube.geometry.parameters.path.v1, scope.pipeWidth, scope.getDonutFatness(value.DataBytesOut), "blue");
//scope.nwScene.add(toParent);
scope.sceneObject.add(toParent);
scope.torusMovementPositive(tube, toParent, value.AvgSRTT);
scope.torusMovementNegative(tube, toChild, value.AvgSRTT);
//start
scope.addToServiceList(value, tube, sphere, serviceTextGeometry, toChild, toParent);
} catch (err) {
console.log(err);
}
}, log);
scope.nwScene.add(scope.sceneObject);
}
});
});
}
//,
//controller: "LandingPageController"
}
};
I am not able to figure out the root cause behind this issue. If the controller property is uncommented then it starts working, otherwise not.

Angular Directive scope undefined

I'm using a directive to parse a xls file and pass the data to a button via scope. The problem is that within the link function I'm binding to the element change event and calling a function that parses the xls file, but scope is undefined within the handleFile function, so I can't pass the data on to the button. What's the correct way to get the data to the button?
angular.module('fileReaderModule')
.directive('xlsReader', function(){
return {
scope: {
search: "&"
},
link: function(scope, e, attr) {
e.bind('change', handleFile);
},
template: '<input type="file" ng-model="xlsFile"><button ng-click="search({stuff: scope.stuff})">Search</button>'
}
function handleFile(scope, e) {
var files = e.target.files;
var i,f;
for (i = 0, f = files[i]; i != files.length; ++i) {
var reader = new FileReader();
var name = f.name;
reader.onload = function(e) {
var data = e.target.result;
var workbook = XLSX.read(data, {type: 'binary'});
scope.stuff = workbook.Strings; // scope not available here
/* DO SOMETHING WITH workbook HERE */
var result = {};
workbook.SheetNames.forEach(function(sheetName) {
var roa = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
if(roa.length > 0){
result[sheetName] = roa;
}
});
};
reader.readAsBinaryString(f);
}
}
})
Inside the templates you don't need to use scope.
Replace this:
template: '<input type="file" ng-model="xlsFile"><button ng-click="search({stuff: scope.stuff})">Search</button>'
with this:
template: '<input type="file" ng-model="xlsFile"><button ng-click="search({stuff: stuff})">Search</button>'
You should also declare your function like this:
angular.module('fileReaderModule')
.directive('xlsReader', function($timeout){
return {
scope: {
search: "&"
},
link: function(scope, e, attr) {
e.bind('change', scope.handleFile);
scope.handleFile(e) {
var files = e.target.files;
var i,f;
for (i = 0, f = files[i]; i != files.length; ++i) {
var reader = new FileReader();
var name = f.name;
reader.onload = function(e) {
//Async code, need $timeout call so angular runs a digest cycle and updates the bindings
$timeout(function(){
var data = e.target.result;
var workbook = XLSX.read(data, {type: 'binary'});
scope.stuff = workbook.Strings;
var result = {};
workbook.SheetNames.forEach(function(sheetName) {
var roa = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
if(roa.length > 0){
result[sheetName] = roa;
}
});
});
};
reader.readAsBinaryString(f);
}
}
},
template: '<input type="file" ng-model="xlsFile"><button ng-click="search({stuff: stuff})">Search</button>'
});

How to return a default image url if the generated image url is not available in angular

I'm new to angular...
$scope.imageUrl[0] = 'images/' + $scope.repos[i].name + '.png';
$scope.imageUrl[1] = 'images/placeholder.png';
$scope.repos[i].imgSrc = (Utils.isImage($scope.imageUrl[0])) ? $scope.imageUrl[0] : $scope.imageUrl[1];
Utils.isImage() is from the following factory:
app.factory('Utils', function($q) {
return {
isImage: function(src) {
var deferred = $q.defer();
var image = new Image();
image.onerror = function() {
deferred.resolve(false);
return false;
};
image.onload = function() {
deferred.resolve(true);
return true;
};
image.src = src;
return deferred.promise;
}
};
});
The image url is generated from an api response object. I'm using Utils.isImage() to check if the generated image url exists in the images folder on the server.
But the (Utils.isImage($scope.imageUrl[0])) is still true even if the image is found on the server or not found.
How can I fix this?
Plunker link - portfolio
The Utils.isImage function return a promise so is always true.
Angular use the $qservice to provide asynchronous functionality. (documentation)
To correctly handle the promise you should use at least the then() function and provide callbacks for a resolved or rejected promise.
Utils.isImage($scope.imageUrl[0])).then(
function() {
// Here is true
$scope.repos[i].imgSrc = $scope.imageUrl[0]
},
function() {
// Here is false
$scope.repos[i].imgSrc = $scope.imageUrl[1]
}
)
Well you can simply write a directive something like this:
myAppModule.directive('noImageIcon', function() {
return {
restrict: 'A',
link: function(scope, element, attr) {
var defaultURL = attr.defaultURL || 'images/plaecholder.png';
attr.$observe('ngSrc', function(newValue) {
if (!newValue) {
element.attr('src', defaultURL);
} else {
var image = new Image();
image.onerror = function() {
element.attr('src', defaultURL);
};
image.onload = function() {
};
image.src = newValue;
}
});
}
};
});
Now your image html tag will be like:
<img ng-repeat="repo in repos" ng-src="images/{{repo.name}}.png" />

Angularjs drag and drop table columns

Hi i use "asutosh" code:
myApp.directive('droppable', ['$parse',
function($parse) {
return {
link: function(scope, element, attr) {
function onDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
if (e.stopPropagation) {
e.stopPropagation();
}
e.dataTransfer.dropEffect = 'move';
return false;
}
function onDrop(e) {
if (e.preventDefault) {
e.preventDefault();
}
if (e.stopPropagation) {
e.stopPropagation();
}
var data = e.dataTransfer.getData("Text");
data = angular.fromJson(data);
var dropfn = attr.drop;
var fn = $parse(attr.drop);
scope.$apply(function() {
scope[dropfn](data, e.target);
});
}
element.bind("dragover", onDragOver);
element.bind("drop", onDrop);
}
};
}
]);
myApp.directive('draggable', function() {
return {
link: function(scope, elem, attr) {
elem.attr("draggable", true);
var dragDataVal='';
var draggedGhostImgElemId='';
attr.$observe('dragdata',function(newVal){
dragDataVal=newVal;
});
attr.$observe('dragimage',function(newVal){
draggedGhostImgElemId=newVal;
});
elem.bind("dragstart", function(e) {
var sendData = angular.toJson(dragDataVal);
e.dataTransfer.setData("Text", sendData);
if (attr.dragimage !== 'undefined') {
e.dataTransfer.setDragImage(
document.getElementById(draggedGhostImgElemId), 0, 0
);
}
var dragFn = attr.drag;
if (dragFn !== 'undefined') {
scope.$apply(function() {
scope[dragFn](sendData);
})
}
});
}
};
});
example here http://plnkr.co/edit/KvJglc?p=preview , to drag and drop table columns, but this code have a little issue, when you drop a column over border or blank area in the headers, the column dissapear. Someone could assist me please?
myApp.directive('angTable', ['$compile',function($compile) {
return {
restrict: 'E',
templateUrl: 'tabletemplate.html',
replace: true,
scope: {
conf: "="
},
controller: function($scope) {
$scope.dragHead = '';
$scope.dragImageId = "dragtable";
$scope.handleDrop = function(draggedData,
targetElem) {
var swapArrayElements = function(array_object, index_a, index_b) {
var temp = array_object[index_a];
array_object[index_a] = array_object[index_b];
array_object[index_b] = temp;
};
var srcInd = $scope.conf.heads.indexOf(draggedData);
var destInd = $scope.conf.heads.indexOf(targetElem.textContent);
swapArrayElements($scope.conf.heads, srcInd, destInd);
};
$scope.handleDrag = function(columnName) {
$scope.dragHead = columnName.replace(/["']/g, "");
};
},
compile: function(elem) {
return function(ielem, $scope) {
$compile(ielem)($scope);
};
}
};
}
]);
Add this 2 lines if(destInd == -1)
destInd = targetElem.cellIndex; after var destInd = $scope.conf.heads.indexOf(targetElem.textContent); and it should work

Resources