How to delete all entries from list? - angularjs

I am trying to delete all entries from list using angular js. I have two directives I communicate between two directive suing shared service. I am able to add the entry in my list .
I want to delete my list when I click on delete button. I blank my array, but I blank my array on service so it is not reflected on my view. How to blank my list?
Here is my code
https://jsfiddle.net/8fjhLqnw/4/
I delete like that
vm.delete = function() {
vm.data = [];
}
It is not reflecting on my view

For deleting all the entries from a list in Angularjs, you can do something like this
$scope.students.splice( $scope.students.indexOf(student), 1);

Use vm.data.length = 0; to clear the array. If you assign a new array, it will not be bound to the view.

Try this:
vm.delete = function() {
vm.data.length = 0;
}
Because you use f.data = sharedData.data to put the data into the scope of the controller, the will share the same array instance, so modifications on sharedData.data will be seen on f.data, as they are the same.
By sharedData.data = [] you assign a new instance of an array to sharedData.data.
From that point, f.data and sharedData.data are separate instances, any modification done on sharedData.data will leave f.data unaffected.
Another way to workaround this:
.controller('f', function($scope, sharedData) {
this.data = sharedData; // and not this.data = sharedData.data
})
and reference the data as f.data.data. This way you can put in new array instances, because you access it directly through sharedData.

Related

after angular $save and push to array item is not added unless I re-run a query

I have a single page app built using the MEAN stack. I am trying to get a list of items to update after a new item is added in angular but it's not working.
$scope.storages = Storages.query();
This works fine and returns my array of storages that I display in the view.
I then have a field to add a new array... to simplify the code it looks like this:
// create a new storage object from $scope.newStorage
var storage = new Storages($scope.newStorage);
I then do various things to the data and finally...
storage.$save(function(){
$scope.storages.push(storage); // doesn't seem to do anything
console.log("new storage", storage); //shows up fine
$scope.newStorage = []; // clear textbox
$scope.showHide.addItemPanel = false; // hides the newStorage form
return $scope.storages;
});
It seems like $scope.storages.push(storage) is not doing anything.
If I use this code at the end:
$scope.storages = Storages.query();
return $scope.storages;
Then it works. But I don't want to have to keep getting all the data from the server each time. How can I solve this and why isn't this working?
If I console.log(JSON.stringify($scope.storages)) it looks like this:
[{"_id":"XXXXXXXXXXXXXXX","_title":"XXXXXXXXX","__v":0,"files":[],"comments":[],"fields":[{"0":{"Title":"XXXXXXXXXXXXX"},"1":{"Category":"coding"},"2":{"Details":"XXXXXXXXX
Thanks in advance!
Read the comments below
storage.$save(function(){
//storage is promise here, not a Storage object you expect
$scope.storages.push(storage);
//because console.log binds to reference
//so after promise resolves, value on reference is changed
console.log("new storage", storage); //shows up fine
//not required at all
return $scope.storages;
});
Simple solution
//bind this to $scope
var storage = new Storages($scope.newStorage);
//like this
$scope.storage = new Storages($scope.newStorage);
//so Resource.$save is promise, when it completes, it will trigger digest
//and your array will be populated
$scope.storage.$save();
$scope.newStorage = [];
$scope.showHide.addItemPanel = false;
$scope.storages.push($scope.storage);
Better solution
//$save accepts callback
storage.$save(function(newStorageFromServer){
//newStorageFromServer is not promise, but actual result from server
//which is Storage instance by default
$scope.storages.push(newStorageFromServer);
//other staff
$scope.newStorage = []; // clear textbox
$scope.showHide.addItemPanel = false; // hides the newStorage form
//return statement is useless
});

angular ionic fails to update for some variables

In my Ionic / Angular framework I update 2 variables inside a service (an $http.get().then() block):
for( var di = day; di <= endOfMonthDate; di++) {
var flavor = days[di - 1];
daysLeftCalendar.push( flavor[1]); // dates right away !
}
var todaysFlavorIndex = -1;
for (var i = 0; i < days.length; i++ ) {
if ((days[i])[0] == day) {
todaysFlavorIndex = (days[i])[1];
todaysFlavorName = flavors[todaysFlavorIndex]; // only updates if you change tabs
}
}
Then I have these accessor methods in my service that get called by my controller:
return {
// both of these are hit after switching to one of the two tabs which both reference these functions
remainingFlavorIndexes: function() {
return daysLeftCalendar
},
getTodaysFlavorName: function() {
return todaysFlavorName
}
};
Then in my only controller I expose these variables like this:
$scope.remainingFlavorIndexes = Calendar.remainingFlavorIndexes(); // this one copies over right away !!
$scope.todaysFlavorName = Calendar.getTodaysFlavorName(); // this one doesn't
Then in my view:
<div> <!-- this one shows up right away -->
{{remainingFlavorIndexes}}
</div>
<div> <!-- these two only show up after switching tabs and returning -->
<img class="scaled-image" src="img/{{todaysFlavorName[2]}}">
</div>
<div style="text-align: center;">
{{todaysFlavorName[1]}}
</div>
How is it that I'm handling these 2 variables exactly the same, but todaysFlavorName is empty (even after the .then call returns)?
And why is it that when I switch tabs and come back they are populated?
Edit:
What is supposed to go into remaining flavor indexes is something like this:
[21,20,13,0,27,12,9,18,1,3,30,29,25,7,6,4,9,18,21,13]
And it works every time.
What is supposed to go into todaysFlavorName is:
[21, "peanut butter", "peanut_butter.jpg", "some meaningless text here"]
And it works only after I switch tabs.
There is a big difference between both. In the case of daysLeftCalendar:
the service has an array
the controller calls the service function that returns a reference to that array
the http callback function pushes elements to this array
So, the controller has a reference to the array that is in the service. Whenever the array is modified in the service, it's also modified in the controller, since the controller and the service both share a reference to the same array.
In the case of todaysFlavorName:
the service defines a variable todaysFlavorName referencing an array
the controller calls the service function that returns a reference to that array
the http callback function doesn't modify this array. It assigns a new array to the variable todaysFlavorName.
So, in the end, the controller has a reference to the original array, whereas the service has a reference to the new array. Which explains why nothing changes in the view: the controller still references the old array.
When you change tab, I assume the controller is reinstantiated, the service function is called again, and the controller gets back the new value from the service.
The fix is quite easy: always get the value to display from the service, instead of caching the value in the controller. Replace
$scope.todaysFlavorName = Calendar.getTodaysFlavorName();
by
$scope.todaysFlavorName = function() {
return Calendar.getTodaysFlavorName();
};
and
{{todaysFlavorName[1]}}
by
{{todaysFlavorName()[1]}}

angular - fail to update array from service

I got a service that contain some contacts (name,phone). The controller has array that contain a reference to the array from the service so for every change on the array all gets updated.
Service:
app.service('ContactManagerService', function()
{
this.Contacts=[];
...
this.AddContact=function(Contact){...};
this.RemoveContact=function(Contact){...};
...
});
First question: Is this a good approach? Should every controller/directive need to have a direct reference to the original array from the service? I have read a lot about setting up some events from the service to the controllers when the array has been changed, but it sound stupid because the array on the controller will be change anyway (because its the same array) and the ng-repeat will be updated automatically.
Second problem: The service has a method that replace the array to new one:
this.ReplaceContacts=function(NewContacts)
{
this.Contacts=NewContacts;
});
The ng-repeat does not update because the controller still got the old reference to the old array. So a refresh need to be done.
I tried to replace the code to this one so the same array's reference wont change, but when the the code enter the foreach, this.Contacts array is undefined and the code stops. Why ?!
this.ReplaceContacts=function(NewContacts)
{
this.Contacts.splice(0, this.Contacts.length); //remove all contacts
NewContacts.forEach(function (contact, index)
{
this.Contacts.push(contact);//place the new ones
});
});
The controller code:
app.controller("myCtrl",
function ($scope,ContactManagerService)
{
$scope.Contacts = ContactManagerService.Contacts;
$scope.AddContact= function (Contact1) {
ContactManagerService.AddContact(Contact1);
}
$scope.RemoveContact = function (ContactID) {
ContactManagerService.RemoveContact(ContactID);
}
});
I hope everything is clear,
Thanks.
Because the callback function passed to forEach isn't bound to the service instance. So this, inside the callback, is not the service.
My advice: avoid this like the plague. It's an enormous source of bugs in JavaScript.
Use
var self = this;
at the top of the service, and use self instead of this everywhere.
Or bind the callback function to the service instance:
NewContacts.forEach(function (contact, index) {
...
}, this);
You can simply push elements to Contacts using Array.prototype.push()
The push() method adds one or more elements to the end of an array and returns the new length of the array.
this.ReplaceContacts=function(NewContacts){
this.Contacts.splice(0, this.Contacts.length); //remove all contacts
Array.prototype.push(this.Contacts, NewContacts);
});
As mentioned in previous anser, context of this in forEach loop is not what you think it is.
A simplification would be to use Array.prototype.concat():
var self = this;
self.ReplaceContacts = function (NewContacts) {
self.Contacts.splice(0, this.Contacts.length); //remove all contacts
self.Contacts.concat(NewContacts);
});

adding new property to an object exposed to scope in angularjs

I have an object that is exposed to $scope and has properties attached to it.
I access this object in my controller and call a service which does little something.
What I need to add to it is new property to the object(which is going to be an array attached to the object as a property) so that updated object is returned to the controller and I can access the elements of this array using data-expression tag{{ }}.
I would like to know in detail about making such manipulations the right way and possible ways of doing it.
Just add the array to the object.
$scope.myobj = {};
...
// sometime later
var numbers = [1,2,3];
$scope.myobj.numbers = numbers;
EDIT:
To answer your question about scope in a service. Scope is not accessible in a service. Typically you ask your service for something IE data. But your service can do anything, like add 2 numbers, or in your case create an array of something that you need to attach to your object.
module.service('MyService', function() {
this.add = function(number1, number2) {
return number1 + number2;
}
this.createMyArray = function() {
// pass in whatever you need to this service in order
// to create the array you need.
// example of just returning a hard coded array
return [1,2,3];
}
});
Then you can inject your service into your controller which has the scope you want to modify.
app.controller('MyController', function($scope, MyService) {
$scope.add = function(number1, number2) {
// Lets use our service to add these numbers and
// assign result to scope variable
$scope.answer = MyService.add(number1, number2);
}
$scope.myobj = {};
$scope.makeArray = function() {
// lets use our service again to create an array
// this time lets add it to a scope object that already exists.
$scope.myobj.numbers = MyService.createMyArray();
}
});
A lot of times services are used to grab/update things from a server, so you will see a lot of examples that make http get/post/put/delete calls. Then from your controller(s) you can use those services to grab data. But again you are not limited to that, your service can simple just hold some static data or helper functions too.

Angularjs: How to filter selected fields from an object array

Lets say I have an object array like this
peoples = [{name:"Joe",age:21,sex:'M'},
{name:"Smith",age:18,sex:'M'},{name:"Sally",age:25,sex:'F'}];
Some of these fields are irrelevant so I need to remove attribute age and sex from all of above objects.
This is the desired output.
[{name:"Joe"},{name:"Smith"},{name:"Sally"}];
Update:
It would be nice if I can use angularjs inbuilt service like $filter.
Well I don't see the need to remove the unnecessary objects since you only access the fields you want. Otherwise you can create a new array from the one you have created chucking out what you don't want.
var peoples = [{name:"Joe",age:21,sex:'M'},{name:"Smith",age:18,sex:'M'},{name:"Sally",age:25,sex:'F'}];
var names = [];
peoples.forEach(function(entry) {
names.push({name:entry.name});
});
console.log("New Names:",names); //[{name:"Joe"},{name:"Smith"},{name:"Sally"}];
Just do:
for( var i = 0; i < peoples.length; ++i ) {
delete peoples[i].age;
delete peoples[i].sex;
}
delete is the keyword created for this

Resources