Object oriented approach with AngularJS

All we need is an easy explanation of the problem, so here it is.

It seems that Angular does not provide a built-in solution to define class instances with properties and methods and that it’s up the developer to build this.

What is the best practice to do this in your opinion?
How to you link this with the backend?

Some of the tips I have gathered use factory services and named functions.

Sources :
Tuto 1
Tuto 2

Thanks for your insights

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

I think that the closest structure to an Object it’s probably a factory, for several reasons:

Basic Syntax:

.factory('myFactory', function (anInjectable) {

  // This can be seen as a private function, since cannot
  // be accessed from outside of the factory 
  var privateFunction = function (data) {
    // do something 
    return data
  }

  // Here you can have some logic that will be run when 
  // you instantiate the factory
  var somethingUseful = anInjectable.get()
  var newThing = privateFunction(somethingUseful)

  // Here starts your public APIs (public methods)
  return {
    iAmTrue: function () {
      return true
    },

    iAmFalse: function () {
      return false
    },

    iAmConfused: function () {
      return null
    }
  }
})

And then you can use it like a standard Object:

var obj = new myFactory()

// This will of course print 'true'
console.log( obj.iAmTrue() )

Hope this helps, I perfectly know that the first impact with angular modules can be pretty intense…

Method 2

You would use an angular service.

All angular services are singletons and can be injected into any controller.

Ideally you would keep only binding/actions on html in your controller and the rest of the logic would be in your service.

Hope this helps.

Method 3

I got idea by evaluating this library : https://github.com/FacultyCreative/ngActiveResource

However this library assumes strict rest so I it wasn’t work for me. What did work for is this:

I created base Model

var app = angular.module('app', []);

    app .factory('Model', function(){
        var _cache = {};  // holding existing instances 
        function Model() {
           var _primaryKey = 'ID',
               _this = this;

              _this.new = function(data) {
                 // Here is factory for creating instances or 
                 // extending existing ones with data provided
               }  

       }

       return Model;
}); 

Than I took simple function extensions “inherits”

Function.prototype.inherits = function (base) {
        var _constructor;
        _constructor = this;
        return _constructor = base.apply(_constructor);
    };

and now I cam creating my models like this

app.factory('Blog', [
   'Model',
   '$http',
   function(Model, $http) {
     function Blog() {
      // my custom properties and computations goes here
      Object.defineProperty(this, 'MyComputed' , {
        get: function() { return this.Prop1 + this.Prop2  }
      });
     }

     // Set blog to inherits model
     Blog.inherits(Model);

    // My crud operations 

    Blog.get = function(id) {
     return $http.get('/some/url', {params: {id:id}}).then(function(response) {
       return Blog.new(response.data);
     });
    }

    return Blog;

   }
]);

Finally, using it in controller

app.controller('MyCtrl', [
   '$scope', 'Blog',
    function($scope, Blog) {
      Blog.get(...).then(function(blog) {
        $scope.blog = blog;
      });
    }
])

Now, there is much more in our Model and extensions but this would be a main principle. I am not claiming this is best approach but I am working pretty big app and it really works great for me.

NOTE: Please note that I typed this code here and could be some errors but main principle is here.

Method 4

As my question does not really reflect the issue I was facing, I’ll just post my approach for the sake of it :
As Domokun put it, rule of thumb is to decouple front and back. But as I am only building a prototype and managing both ends, I would like to keep things in only one place and let the rest of the application use the central information as a service.

What I want to do here is to build a form through ng-repeat containing the model fields and most importantly how to display information in the form (e.g. ‘Last name’ instead of ‘lastname’)

So as I started working around with mongoose models here’s what I have managed to do :

Firstly, it is possible to pass the mongoose schema of a model from node side to angular side with an app.get request with the following response :

res.send(mongoose.model('resources').schema.paths); 

this spitts out an object containing all fields of the ‘resources’ collection. On top of that I included some additional information in the model like this :

var resourceSchema = new Schema({
    _id: { type: Number },
    firstname: { type: String, display:'First name' },
    lastname: { type: String, display:'Last name' }
});

mongoose.model('resources', resourceSchema);

So basically I can retrieve this symmetrically on angular side and I have all I need to map the fields and display them nicely. It seems I can also describe the validation but I’m not there yet.

Any constructive feedback on this approach (whether it is valid or totally heretic) is appreciated.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply