Adding files to $scope in AngularJS controller - angularjs

I have the following input element:
 <div class="form-group">
    <label>Attach BOL Document</label>
       <input name="file" type="file" class="form-control" onchange="angular.element(this).scope().uploadFile(this.files)" />
 </div>
In my controller (outside of any function) I set a variable like this:
$scope.fd = new FormData();
and I have the following function defined that fires onchange of the input element as seen above:
$scope.uploadFile = function (files) {
console.log(files[0]);
$scope.fd.append("file", files[0]);
console.log($scope.fd);
};
The first console.log outputs the File object as I expect so I know that is being passed into my $scope. The problem is the second console.log outputs an empty FormData object. The File object is not getting appended??
I thought maybe this was something to do with the fact that I am declaring $scope.fd outside of the UploadFIle function, but even declaring it inside the function does not work...
Why???

Well I figured out whats going on here. Its got nothing to do with AngularJs. You cannot inspect the keys added to a FormData object. See this question for a reference
How to inspect FormData?
This really stinks... So until I get the server side code ready and I actually POST the data I cant tell if the file is actually getting appended. I feel certain it is however I cant validate this.

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'".

Angular js UI grid is not getting updated with new content

I am calling $http.get to get new content from the server for angular ui grid. On change of date in the datepicker I trigger an ng-change event to make another http call to get new content. The call is successful but the grid is not updated with new content.$scope.grid.core.notifyDataChange() throws error when called inside the http success call back.Please suggest ways to update the grid with new content.
Please find the plnkr code. when I click load button, I want to update grid with new JSON data using http call but it is not updating grid. http://plnkr.co/edit/S2A3scEoO6QIGFbru3Lr?p=preview
The problem with your example is inside $http's success method(lines 256-260).
$http.get(...).success(
function(data){
$scope.roData = data;
});
There you are just putting your data inside a scope property ($scope.roData), but then you're not doing anything with that scope property.
Furthermore you're trying to assign a wrong value to uiGrid.gridOptions.data with the lines:
if($scope.gridOptions.data ==='rData'){
$scope.gridOptions.data = 'roData';
}
But you did 2 mistakes:
Treating variables as string, and this is not going to work. Inside your JS files you need to access your scope with $scope.nameOfVariable not by using their names as strings like 'nameOfVariable'.
You put these lines outside of your success method, so they are executed before you actually get your data.
I managed to edit your plunker and make it work, you can find it here.
What I did was putting your lines together and fix the name error. I did not put there any if since I don't know what logic you wanted to accomplish.
$http.get(...).success(
function(data){
$scope.roData = data;
$scope.gridOptions.data = $scope.roData;
});

Clearing a text entry field after processing the input

Having completed CodeSchool's AngularJS course, I'm trying to go back through and use what I've learned to build a simple to-do app. I've gotten it to the point where I can add entries to a list, but I'm not able to clear the text entry field after I've used the input. Here's my JSFiddle.
Specifically, here's my addComment() function:
card.addComment = function(newComment) {
card.comments.push(newComment.text);
newComment = {text: ""};
};
And the corresponding Angular HTML:
<form ng-submit="card.addComment(newComment)">
<input name="comment" placeholder="Add comment" ng-model="newComment.text">
</form>
At first I was passing the data in as a string (<input ng-model="newComment"> instead of newComment.text), but then I remembered that strings get passed by value, not by reference. I figured newComment was being blanked in the function but not passed back through Angular to the document. But even after I changed newComment to an object so it would be passed by reference, it made no difference--clearing the value in JavaScript has no effect on the page. What am I doing wrong?
I remembered that strings get passed by value, not by reference.
This line of reasoning is incorrect. Everything in JavaScript gets passed by object reference. See this question: Is JavaScript a pass-by-reference or pass-by-value language?
Replacing the raw string with an object does potentially buy you some affordance, though. However, whether or not it's a string or an object (and indeed, a string is an object!), newComment = someValue will never work.
Instead, you'll need to set the text property on the object. This doesn't create a new object, it just modifies a property, so the reference is preserved. Try this instead:
newComment.text = '';
Try this:
card.addComment = function(newComment) {
card.comments.push(newComment.text);
newComment.text = "";
};
What you're doing is creating a new object on the scope and breaking the binding which was set up on the original object. By updating the text property only, you leave the binding intact and achieve your goal of clearing the input field to which it is bound.
You can rest a form which may do what you require
document.getElementById("myForm").reset();

Cannot access scope variable set using Mongoose query within controller

In my MEANJS app. I am setting the value of a scope variable to a query result, from my controller function
$scope.myVar = User.query();
console.dir($scope.myVar); //Returns all the documents from the DB correctly
console.log('User's name is : ' + $scope.myVar[0].name); //This comes as undefined
Somehow, in the very next line when I am trying to open the name field within the same controller function, it comes as undefined. Also, the entire result is being read absolutely correctly in my view file. So when I call
{{myVar.name}}
within my view file it outputs the name correctly. I cannot understand this behavior at all. This is my first time working with Angularjs, and I could have missed something basic, but I appreciate any help at this point.
Edit - Also the length of $scope.myVar is always 0 within the controller
Basically User.query() returns a promise object, so you need to update you $scope object inside promise success.
Code
User.query().$promise.then(function(res){
//you will get response here in data obj
$scope.myVar = res;
console.dir($scope.myVar);//Returns all the documents from the DB correctly
console.log('User's name is : ' + $scope.myVar[0].name); //This comes as undefined
});
EDIT: Found the answer. The callback functions in meanjs are in this format:
var myObj= User.query(function(response) {
console.log('Inside success response');
//Can access myObj values here easily
}, function(errResponse) {
console.log('Inside error response ' + errResponse);
});
I wasn't able to figure out how to access my $scope.myVar within the controller, but I completed a workaround by creating my own factory method to retrieve data the way I wanted it sorted. The problem of not being able to access these query results is really posing a problem in other parts as well. So if anyone has an answer, please do let me know.
For now posting the link I used to figure out how the MEAN.JS factory method needs to be plugged in. Hope this helps someone.
https://groups.google.com/forum/#!searchin/meanjs/query()/meanjs/4R7rIolH9bs/P1R4YlKgowUJ

How to use $resource in AngularJS properly for building a client app?

I've been following this tutorial http://draptik.github.io/blog/2013/07/28/restful-crud-with-angularjs/. I implemented a Grails backend with it instead of the Java one in the tutorial.
I've got the data coming back and forth, with one issue. If I create/update/delete a user, I don't see the changes reflected on my user list when I am redirected back. I have to refresh the page to see the updates.
Looking at the network traffic for an edit, it looks like it does a PUT and fires off the GET before the PUT is complete. Assuming this is because $resource returns a promise so things can be done asynchronously. So how do I handle this so that when $location redirects me, my list is up to date?
I'm guessing the options are to wait for the PUT to complete before redirecting/querying for the list, or to somehow manually manage the $scope.users to match the request?
Or maybe this tutorial is just a bad example? Maybe there is a better way to do it (still using $resource)?
Note: I've seen Restangular out there, and I've seen $http with success callbacks, but I would like to understand the situation above.
One way to overcome this issue would be to not redirect to the list page, till you get a callback, and then do a redirect. You can show some busy indicator till that time. The resource call looks like this.
resource.update(config,data,function() { //gets called on success},
function(error) { //gets called on failure});
In real life scenario waiting for the response of update makes sense as you want to handle the error and success scenarios on the same page.
I don't see your code anywhere so i'm just assuming (based on what you wrote and your current problem)
You are probably doing a full (or partial) get each time you changed a user and (re)binding the result to your scope. Doing this in the callback of the resource should actually start the digest cycle angular does to update modified objects. If you had been doing the fetching outside $resource - for example with custom/jquery ajax you would need to execute $scope.$apply()
What i really don't understand you would need to wait for the callback. You already know you added/modified a user. Instead of 'detaching' that user from your scope, modify it, post it to your rest server, then wait for callback, and reinserting it into the scope - why not modify it directly in the list/array you put on your scope?
var users = Users.get(function () {
$scope.users = users.record; // bind the resulting records to the scope
});
$scope.updateUser = function (user) {
resource.update(...); //pseudo
};
Then in your html, you will keep a reference to the currentUser and the div-list will update automaticly.
<div ng-repeat="user in users" ng-click="currentUser=user">{{user.Name}}</div>
<input ng-model="currentUser.Name">
<button ng-click="updateUser(currentUser);">Update</button>
If you don't want to see the update in the list while you type, but only once your callback fires or when you hit the button, would would instead use another ng-model for your input like this:
<input ng-model="tempUser.Name">
And you would then copy the value other in either the updateUser method or in the resource callback like this:
$scope.updateUser = function (user) {
user.Name = $scope.tempUser.Name; // should update automaticly
resource.update(...) // pseudo
}
Hope it helped!

Resources