Getting id undefined in angularJs service - angularjs

I have followed tutorial : http://viralpatel.net/blogs/angularjs-service-factory-tutorial/
But, when I try to save a new record, I am getting newcontact.id as undefined and unable to save new record.
What would be the problem?

you need to add this piece of code
var original = {itemCategory:null,itemName:null,
itemPrice:null,purchaseDate:null,applianceType:null,
insStatus:null,id:null};
$scope.newitem = angular.copy(original);
and edit the saveItem function as this
$scope.saveItem = function () {
alert("add new");
DataStoreService.save($scope.newitem);
$scope.newitem = angular.copy(original);
}
here is the working Plunker
please not that i remove the <script src="angular-dropdowns.min.js"></script> and the ngDropdowns dependency of var app = angular.module('app', ['ngDropdowns']);, to get rid some console errors which are not causing this issue.
The cause of the problem
the problem of getting id undefined is, you didn't define a variable called $scope.newitem with in the controller, instead you straightly use newitem with in the HTML, then your controller dosen't know about this newitem until you change any input.
if you change any input say itemName then the controller knows there is no $scope variable called newitem, then the angular will create the newitem object and a itemName property inside that newitem object , after changing itemName input say u change the itemPrice then the controller search for the newitem object and put the property itemPrice in to the object, ok now you have two properties inside the newitem, like wise the process goes with your inputs, but the id field is a hidden field and your not going to change the value inside html, that means in your newitem object you don't have id property. that`s why its getting undefined.
to scarify,
add a line as the first statement as console.log($scope.newitem); in the $scope.saveItem function and check the $scope.newitem object, here is the Plunker to test it
press save without changing any input
this red color can not read id of undefined error is because we pass the $scope.newitem to the service which is undefined, so the script can not get the id field of item which is undefined in the line of alert("save"+ item.id);). item is undefined
change only the itemName and press save
here you will get a alert saying saveundefined this is because of the alert in line alert("save"+ item.id);). In this line item which is not undefined but the id property of the object is not set , so item.id is undefined, that's why its alert saveundefined. item is defined but item.id is undefined
Solution
create a object to hold default values of all the newitem properties
var original = {itemCategory:null,itemName:null,
itemPrice:null,purchaseDate:null,applianceType:null, insStatus:null,id:null};
get a deep copy of that object and assign it to newitem
$scope.newitem = angular.copy(original);
after saving the newitem reset the newitem object to default object we defined,
$scope.saveItem = function () {
alert("add new");
DataStoreService.save($scope.newitem);
$scope.newitem = angular.copy(original);
}

Related

Value from $rootScope is not loaded properly

So I'm basically trying to get a property from my $rootScope when the page loads. I need this property so I can display the value in my form.
After testing this:
console.log("DEBUG $rootScope", $rootScope);
console.log("DEBUG $rootScope.localClient", $rootScope.localClient);
I've noticed that $rootScope contains a localClient property, but $rootScope.localClient is undefined. Why is this?
See console screen below.
Here is where I fill the localClient object
function setClient(client, tvaNumber) {
if (tvaNumber) {
if (angular.isUndefined($rootScope.localClient))
$rootScope.localClient = {};
$rootScope.localClient[tvaNumber] = client;
}
}
Try accessing it like this,
console.log("DEBUG $rootScope.localClient", $rootScope['localClient']);
You must make sure the attribute loaded before use it, because JavaScripte always pass a reference to an object. Or you can try console.log(JSON.parse(JSON.stringify($rootScope)) get the real value.
One example:
var a = {}; console.log(a);a.test = '1';

How to select value inside an object

I'm trying to store 1 or more values that are inside an array into a scope. This is the result of my JSONP service,
angular.callbacks._7({
"id":157336,"results":[
{"id":"53db3c790e0a26189a000d09","iso_639_1":"en","key":"ePbKGoIGAXY","name":"Trailer 3","site":"YouTube","size":1080,"type":"Trailer"},
{"id":"550df44b9251413554004d43","iso_639_1":"en","key":"KlyknsTJk0w","name":"Own it today","site":"YouTube","size":720,"type":"Trailer"},
{"id":"533ec6fcc3a3685448009ccc","iso_639_1":"en","key":"nyc6RJEEe0U","name":"Teaser","site":"YouTube","size":720,"type":"Trailer"},
{"id":"5376ab510e0a26141c0005a8","iso_639_1":"en","key":"zSWdZVtXT7E","name":"Trailer","site":"YouTube","size":720,"type":"Trailer"},
{"id":"545da247c3a3685362005187","iso_639_1":"en","key":"Lm8p5rlrSkY","name":"Trailer 2","site":"YouTube","size":1080,"type":"Trailer"}
]
})
And I'm trying to store all the key values inside a scope called $scope.youtubeTrailer
But if I do it like this,
$scope.youtubeTrailer = response;
console.log ($scope.youtubeTrailer)
The scope consists of an object (the movie) and inside that object is an array with the 5 id's. So what would be the correct selector for something like this?
If I search like this,
console.log ($scope.youtubeTrailer.key)
I get an 'undefined´
* EDIT *
I've tried to solution below,
movieAdd.trailer(movie.id)
.then(function(response){
$scope.youtubeTrailer =[];
console.log ($scope.youtubeTrailer)
angular.forEach(response.results, function(item){
console.log ('Hello world')
if (item.hasOwnProperty('key')) {
$scope.youtubeTrailer.push(item.key);
}
});
The console.log ($scope.youtubeTrailer) shows that the scope is empty. And the forEach function doesnt fire because the Hello log doesn't get shown in the console. If I change $scope.youtubeTrailer =[]; into $scope.youtubeTrailer = response; I do have the object in the scope but still the forEach doesn't fire.
* EDIT 2 *
By changinge response.results into response the forEach does fire.
* EDIT 3 *
I've got it somewhat working. I was getting the array in the scope, but when I saved the scope value in the create function it showed as null in the database. That's because I was trying to save an array. Using javascripts join I converted the array to a string which can be saved.
movieAdd.trailer(movie.id)
.then(function(response){
$scope.youtubeTrailer = [];
angular.forEach(response, function(item){
if (item.hasOwnProperty('key')) {
$scope.youtubeTrailer.push(item.key);
var youtubeArray = $scope.youtubeTrailer
var youtubeString = youtubeArray.join();
The code below basically is looping through the response.results array, which contains 5 objects. Each oject is assigned to the variable item. Check item has property of key, if true, add the value of item.key to $scope.youtubeTrailer.
$scope.youtubeTrailer =[];
angular.forEach(response.results, function(item) {
if (item.hasOwnProperty('key')) {
$scope.youtubeTrailer.push(item.key);
}
});
Here is the link for Angular ForEach.
$scope.youtubeTrailer isn't just an object, it contains an array and its inside that array that the key field is. So, you're going to need to access the five interior items with an array access. e.g. $scope.youtubeTrailer.results[0].key

angular-dialog-service update parent scope data object

I've a template:
<p class="text-right">
<a ng-click="editTherapeuticProposal(meow.accepted_tp)" class="fa fa-pencil"></a>
</p>
which calls the editTherapeuticProposal function defined in its controller, passing it the meow.accepted_tp object (here I use angular-dialog-service: https://github.com/m-e-conroy/angular-dialog-service):
// here tp is equal to meow.accepted_tp
$scope.editTherapeuticProposal = function(tp) {
dialogs.create('surgeon/templates/create_edit_therapeutic_proposal.tpl.html', 'SurgeonCreateEditTherapeuticProposalCtrl', {scope: $scope, tp: tp}, { copy: false });
};
tp is an object.
Then in the dialog controller I display a form in order to let the user modify tp. I do some stuff, the relevant ones are:
// data is the object received by the dialog controller: {scope: $scope, tp: tp}
if(typeof data.tp != 'undefined') {
$scope.therapeuticProposal = angular.copy(data.tp);
}
I copy the object to work on a different object (I don't want data to be updated if not saved)
When pressing the save button in the dialog, the following function runs:
var complete = function(tp) {
data.tp = tp;
//...
}
Ok, the problem is that meow.accepted_tp in the parent scope doesn't get updated. If I do
var complete = function(tp) {
data.tp.title = 'meow';
//...
}
Its title gets updated. There is clearly something wrong with the prototypal inheritance, I know that in order to get variables updated they should be properties of an object, but tp is already passed as an object property (of the data object). Any ideas?
Edit
After re-reading the angular-dialog-service docs, you can pass a result back using modalInstance. It sounds like this is what you want to do.
The reason your binding isn't working is because you're changing the object reference from a child scope, rather than a property on the object bound (which is why data.tp.title = 'meow' works).
Anyway, for your case, try this:
// here tp is equal to meow.accepted_tp
$scope.editTherapeuticProposal = function(tp) {
var dlg = dialogs.create('surgeon/templates/create_edit_therapeutic_proposal.tpl.html', 'SurgeonCreateEditTherapeuticProposalCtrl', {scope: $scope, data: data}, { copy: false });
dlg.result.then(function(tp) {
// Get the result and update meow.accept_tp
$scope.meow.accepted_tp = tp;
});
};
Then in the dialog, when you complete, do:
var complete = function(tp) {
$modalInstance.close(tp);
}
For an example, see http://codepen.io/m-e-conroy/pen/rkIqv, in particular the customDialogCtrl (not customDialogCtrl2) is what you want.

Firebase $save doesn't work inside an event handler function

I must be missing something really basic. I have an input box where the list name is entered. The name is then saved to the Firebase.
When using $watch, it works just fine. However, if done through ng-keyup event, it returns the following error
TypeError: undefined is not a function.
What am I missing?
HTML:
<input id="which_list" ng-keyup="enterThis($event)" ng-model="which_list.name" >{{which_list.name}}</span>
Controller:
$scope.which_list = sync.$asObject();
$scope.$watch('which_list.name', function() {
gDataService.which_list.name= $scope.which_list.name;
$scope.which_list.$save() // THIS WORKS
// $scope.which_list => d {$$conf: Object, $id: "id", $priority: null, name: "to1_list", $save: function…}
.then(function(){
console.log($scope.which_list.name);
});
});
$scope.enterThis = function(event){
if (event.keyCode === 13) {
gDataService.which_list.name= $scope.which_list.name;
$scope.which_list.$save(); // THIS DOESN't WORK
// $scope.which_list = Object {name:"list_name"}
}
};
EDIT: In the comment, I included the value of $scope.which_list shown at the breakpoint.
Currently as you are changing in scope which_list converting to plain old JavaScript objects (POJO), I believe you need to unable 3 way binding between scope variable and $asObject().
Code
var which_list = sync.$asObject();
// set up 3-way data-binding
which_list.$bindTo($scope, "which_list");
Update
Also as you are using $scope.which_list object which contains name and other property,So do initialize it on starting of your controller like
$scope.which_list = {}
Hope this could help you, Thanks.

need help to understand angular $watch

say I have a album list and user can add album
controller.albumList = function($scope, albumService) {
$scope.albums = albumService.query();
$scope.$watch('$scope.albums',function(){
$scope.albums.$save($scope.albums)
})
$scope.addalbum= function(){
$scope.albums.objects.push(album);
}
};
get a album list from server and show them
user can add album
watch the albums list ,when change happend save them to the server.
the problem is the $watch always fired, I did not even trigger the addalbum method, and every time I refresh the page a new album is created.
I follow the the code in todeMVC angular
here is the example code
var todos = $scope.todos = todoStorage.get();
$scope.newTodo = '';
$scope.editedTodo = null;
$scope.$watch('todos', function () {
$scope.remainingCount = filterFilter(todos, { completed: false }).length;
$scope.completedCount = todos.length - $scope.remainingCount;
$scope.allChecked = !$scope.remainingCount;
todoStorage.put(todos);
}, true);
please help me understand this
this is a solution:
$scope.$watch('albums', function(newValue, oldValue) {
if (angular.equals(newValue, oldValue)) {
return;
}
$scope.albums.$save($scope.albums);
}
After a watcher is registered with the scope, the listener fn is called asynchronously (via $evalAsync) to initialize the watcher. In rare cases, this is undesirable because the listener is called when the result of watchExpression didn't change. To detect this scenario within the listener fn, you can compare the newVal and oldVal. If these two values are identical (===) then the listener was called due to initialization.
More about a $watch listener: $watch at angularjs docs
Firstly, you do not have to specify the scope object when referencing to a property of the scope. So, replace:
$scope.$watch('$scope.albums', ...)
with the following:
$scope$watch('albums', ...)
Now about your issue. $watch is triggered each time the value of the object / property being watched changes. This includes even those cases when the values are yet to be assigned, such as undefined and null. Thus, if you wish that the save should happen only when a new album is added, you can have code similar to:
//Makes assumption that albums has a length property
$scope.$watch('albums.length', function () {
//Check for invalid cases
if ($scope.albums === undefined || $scope.albums === null) {
return;
}
//Genuine cases.
//Proceed to save the album.
});
With this, the $watch is still triggered in unwanted scenarios but with the check, you avoid saving when the album has not changed. Also, note that your $watch triggers only when the length of the albums object changes. So, if an album itself is updated (say an existing album name is changed), then this watch is not triggered. You can change the watch property based on your needs. The watch property mentioned here works only when a new album is added.

Resources