frictionlesspulley
frictionlesspulley

Reputation: 12368

adding behavior to javascript objects in angular

I am new to using angular and had a question regarding adding behavior to objects in angular.

I have a case in which I have getting an object / or array of objects say person using $http

var person =
    {
      id : 123,
      firstname : "james",
      lastname : "bond",
      username : "james00",
      profileGuid : "DSKFSJKFBSFBJBSFKJBAKBDS",
      projects : [
             {
                id : 1,
                name : "gold finger"
             }
       ] 
    }

I want to add behavior like say

 var spyBehavior = 
 {
    greet : function(){
        return this.lastname + " " + this.firstName + " " + this.lastName;
    },

    hasExperience : function(){
      this.projects && this.projects.length && this.projects.length > 0
    }
 }

Currently I do this with angular.extend(person, spyBehavior)

Upvotes: 0

Views: 155

Answers (3)

rvignacio
rvignacio

Reputation: 1740

I use to define a prototype object in a Factory provider:

angular.module('MyApp').factory('SpyBehaviour', function(){
    var SpyBehaviour = {
        greet : function(){
            return this.lastname + " " + this.firstName + " " + this.lastName;
        },

        hasExperience : function(){
            this.projects && this.projects.length && this.projects.length > 0
        }
    };

    return SpyBehaviour;
});

Then, I create a new object with my prototype and extend it with the results from the $http service. If you use the transformResponse function, then the $http promise will be resolved with your extended objects.

$http.({
    method: 'GET',
    url: '/persons',
    transformResponse: function (data) {
        var persons = JSON.parse(data);

        return persons.map(function (person) {
            return angular.extend(
                Object.create(SpyBehaviour),
                person
            );
        });
    }
});

Upvotes: 1

link
link

Reputation: 1676

If you are retrieving your models from an HTTP backend, AngularJS has a cool feature called transformResponse. You can specify a transformResponse function for specific $http calls. The function will receive as an argument the response from the http request, manipulate it according to your implementation, and then return it. Of course, since angular $resources are built on top of $http, you can use transformResponse in both.

In short, if you want to receive an array of people and decorate it with some functionalities, this is what I would do:

  • Implement a People $resource that maps to your API;
  • Implement a function that, given an array of people, adds the desired behavior.
  • Specify the aforementioned function as the transformResponse parameter of the People resource.

And you are done. What you will get at the end of your request is an array of people with the additional functions. You can do exactly the same with a simple $http request, the transformResponse attribute can be specified in the same way.

See also this short egghead.io tutorial.

Upvotes: 0

23tux
23tux

Reputation: 14736

I think what you want is some kind of model. I always define my models the following way as a factory, because services are singletons.

angular.module('myApp').factory('User', function() {
  var _greet = function() {
    console.log("hello");
  };
  var User = function(data) {
    angular.extend(this, {
      email: null,
      name: null
      greet: _greet
    }, data);
  };
  return User;
});

Then, you can inject your User "model" in any module you want. If you want to get a new instance of that model, just do a

var user = new User(data);

Following a single responsibility approach, this object is kinda stupid. It only knows it's own properties, what to do with them and so on. If you want to add some behaviour like updating this object through $http, just inject the $http service into your User model and do the stuff you want. Just be sure, not to create unnecessary dependencies with other models.

Upvotes: 2

Related Questions