Where to put model data and behaviour? [tl; dr; Use Services] Where to put model data and behaviour? [tl; dr; Use Services] javascript javascript

Where to put model data and behaviour? [tl; dr; Use Services]


You should use services if you want something usable by multiple controllers. Here's a simple contrived example:

myApp.factory('ListService', function() {  var ListService = {};  var list = [];  ListService.getItem = function(index) { return list[index]; }  ListService.addItem = function(item) { list.push(item); }  ListService.removeItem = function(item) { list.splice(list.indexOf(item), 1) }  ListService.size = function() { return list.length; }  return ListService;});function Ctrl1($scope, ListService) {  //Can add/remove/get items from shared list}function Ctrl2($scope, ListService) {  //Can add/remove/get items from shared list}


I'm currently trying this pattern, which, although not DCI, provides a classical service / model decoupling (with services for talking to web services (aka model CRUD), and model defining the object properties and methods).

Note that i only use this pattern whenever the model object needs methods working on its own properties, that i'll probably use everywhere (such as improved getter/setters). I'm not advocating doing this for every service systematically.

EDIT:I used to think this pattern would go against the "Angular model is plain old javascript object" mantra, but it seems to me now that this pattern is perfectly fine.

EDIT (2): To be even clearer, I use a Model class only to factor simple getters / setters (e.g. : to be used in view templates). For big business logic, i recommend using separate service(s) that "know" about the model, but are kept separated from them, and only include business logic. Call it a "business expert" service layer if you want

service/ElementServices.js (notice how Element is injected in the declaration)

MyApp.service('ElementServices', function($http, $q, Element){    this.getById = function(id)    {        return $http.get('/element/' + id).then(            function(response)            {                //this is where the Element model is used                return new Element(response.data);            },            function(response)            {                return $q.reject(response.data.error);            }        );    };    ... other CRUD methods}

model/Element.js (using angularjs Factory, made for object creation)

MyApp.factory('Element', function(){    var Element = function(data) {        //set defaults properties and functions        angular.extend(this, {            id:null,            collection1:[],            collection2:[],            status:'NEW',            //... other properties            //dummy isNew function that would work on two properties to harden code            isNew:function(){                return (this.status=='NEW' || this.id == null);            }        });        angular.extend(this, data);    };    return Element;});


The Angularjs documentation clearly states:

Unlike many other frameworks Angular makes no restrictions orrequirements on the model. There are no classes to inherit from orspecial accessor methods for accessing or changing the model. Themodel can be primitive, object hash, or a full object Type. In shortthe model is a plain JavaScript object.

AngularJS Developer Guide - V1.5 Concepts - Model

So it means that's up to you how to declare a model.It's a simple Javascript object.

I personally won't use Angular Services as they were meant to behave like singleton objects you can use, for example, to keep global states across your application.