简体   繁体   中英

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)

  • What is the pros/cons of adding behavior using such spyBehavior object?
  • Should this be defined as an angular service ? - in which case, I loose the reference of this
  • Should this be outside angular world and exist as a simple javascript object which wraps around $http output ? how do I do it?

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.

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

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 $resource s 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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM