Intro

{
name: "Tom Acree",
occupation: "Software Engineer / Consultant",
company: "Transcordia LLC",
companyUrl: "www.transcordia.com",
Experience: ["JQuery", "Sencha/Ext-JS", "Dojo", "angular"]
} 
I have been working with AngularJS on a project around 6 months

Goals

  • Better Understanding of how Models fit into the overall framework
  • Some best practices, or maybe gotchas
  • Making models richer

Defining the Model in Angular

Angular is an opinionated framework

...Except for the most part when it comes to models

$scope is NOT the model, it holds a reference to the model  

Models are data structures within the application and are applied to  $scope

 

The data received from an AJAX call is not always the model we want.      Models may need to be transformed

Models need business logic/behavior


Best Practices

Models should be managed, but not in controllers or directives


Where we've been:

Controllers with logic to manage the model, business rules, etc.

Where we want to go:

Slim controllers and richer models

What We're doing

Move management of Models into services


Model objects should be what you bind to

...not properties of a model

Misko Hevery: "...bindings should have a dot..."


Do This: {{movie.title}}

Not This: {{title}}


See the following explanation

Nested Scopes in AngularJS



My Goals in Working with Models

  • Works with REST api.  This is my focus today.
  • Models can be enhanced with behavior
  • Support for nested objects
  • Support sparse vs detailed versions of a model
  • Caching
    • Where possible, avoid trips to the server
  • Traversable Relationships such as parent/child

Managing logic-Behavior in Models

Move logic to a service

 angular.module('ngColApp')
    .factory('movieUtils', function () {
        return {
            calculuateProfit: function (movie) {
                // do calculation
            },

            getLengthInHours: function (movie) {
                // do calculation
            }
        };
    });

  • Service uses data as parameter
  • Functional approach, no prototypes, base classes, ...
  • Testable and mockable
  • Gets unwieldy
  • I'd prefer methods on my entities themselves

Encapsulate logic within a mixin or function definition and apply a transformer

  • Logic is in the Model itself
  • Easily testable
  • Easy to implement
  • Uses classes and prototypes 


Interesting approach at odetocode

This was what I wanted, what else is there?

Existing Frameworks

  • Restangular
  • BreezeJS
  • ngActiveResource
  • angular-data
  • others...?

Restangular

https://github.com/mgonto/restangular

See the  presentation

First discovered in "ng-book"

Proposed as alternative to $Resource

Full Featured
Easy to use
Has much of what I hoped for

Angular Data

http://angular-data.pseudobry.com/


Looks Promising

Not Yet Released

Powerful cache support

BreezeJs

http://www.breezejs.com/documentation/breeze-angular-service


Now with built in support for angular

Large Community it seems

Fully featured, maybe more than I need?

Worth trying out

ngActiveResource

https://github.com/FacultyCreative/ngActiveResource


Full featured implementation of Active Record style models

Had traction, good start on egghead.io

Not overly active, but that changes

Very opinionated design

So then I found this...

Ben Teese


https://www.youtube.com/watch?v=JfykD-0tpjI

And his blog post


The approach

Uses Restangular

Leverages Mixins over Prototypes

SIMPLE!!!

Not too intrusive as long as you are ok with Restangular

See Example

Restangular in Brief

 function restangularShow() {
    // First way of creating a Restangular object. Just saying the base URL
    var baseAccounts = Restangular.all('accounts');

    // This will query /accounts and return a promise.
    baseAccounts.getList().then(function (accounts) {
        $scope.allAccounts = accounts;
    });

    // Just ONE GET to /accounts/123/buildings/456
    Restangular.one('accounts', 123).one('buildings', 456).get();
    
    var newAccount = {name: "Bob"};

    // POST /accounts
    baseAccounts.post(newAccount);

    // Second way of creating Restangular object. URL and ID :)
    var account = Restangular.one("accounts", 123);

    // GET /accounts/123?single=true
    account = account.get({single: true});
}


Made with Slides.com