0

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.

4
  • Can you post your controller code please? Commented Aug 22, 2015 at 12:51
  • In this.Contacts.push(contact);, this has a different context Commented Aug 22, 2015 at 12:53
  • It's correct, but I don't like it. It breaks encapsulation by exposing the service internals everywhere, and encouraging controllers to directly modify the array instead of going through the service methods. Commented Aug 22, 2015 at 13:09
  • Okay then what is your suggestion for fixing this? Commented Aug 22, 2015 at 13:11

3 Answers 3

2

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);
Sign up to request clarification or add additional context in comments.

3 Comments

thanks man but i didnt fully understand what var self = this will do?
It will assign this (the service) to the variable self, and this variable will thus point to the service as this does. Except that self will always point to the service, whereas this doesn't always, depending on where you use it (like, for example, in a callback function).
thanks. Any chance you can tell me if the approach on my first question is currect? have not find anything usefull over google.
1

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);
});

Comments

1

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);   
});

5 Comments

First question really depends on use case.
so in my example is it a good approach? I have not found something usefull in google
direct reference can be very helpful
I read that the controller should not get direct access to delete/update/add on any data.
That's fine, but doesn't mean not using direct reference to array in controller. If add/delete is done in service the referenced array in controller will still reflect changes

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.