Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Angular's Models Conform to the M in MVC Just Fine

DZone's Guide to

Angular's Models Conform to the M in MVC Just Fine

You should be able to attach two views to the same model (directly or indirectly) and it should just work. Consequently, either view can update the model, with changes appearing in the other view automatically. You should also be able to compose models from other models, and that should just work too. So, let's see...

· Web Dev Zone ·
Free Resource

Bugsnag monitors application stability, so you can make data-driven decisions on whether you should be building new features, or fixing bugs. Learn more.

Note: MVC in this context is a 1978 design pattern, not an ASP.NET related technology that Microsoft released in 2007.

Models in MVC

You should be able to attach two views to the same model (directly or indirectly) and it should just work. Consequently, either view can update the model, with changes appearing in the other view automatically. You should also be able to compose models from other models, and that should just work too.

Angular’s Conformance

I’m only testing Angular 1.5 here (not 2.0.0-beta.x or above), but yet it works as expected.

Take a look at the running application: paulhammant.com/demos/angulars-model-conforms-to-the-m-in-mvc/index.html

Screenshot: Click to see the interactive iframe version

Expand one of the expandable items and click on the number of calories for the item. You can now edit that (span becomes an input). Note that changes you make impact the other tree-table. If you scroll down, the change is also apparent in the underpinning models. Therefore, M, V, and C behave as you’d expect.

Note that I’m composing models, and Angular knows what’s connected to what (see source links below).

Source

To view the 73-line source of that page go to paulhammant.com/demos/angulars-model-conforms-to-the-m-in-mvc/index.html and right click to "view source".

Or, take a look at the 58-line JavaScript source for the Angular controller logic

angular.module('project', ['ngResource'])
    .factory('JsonGetter', function ($resource) {
        var JsonGetter = $resource(':q');
        return JsonGetter;
    })
    .controller('TheController', function ($scope, JsonGetter) {
        function insertItems(toIterateOver, type, plural, verb) {
            verb = verb || "consumed";
            plural = plural || "items";
            angular.forEach(toIterateOver, function (date) {
                if (!(date.when in $scope.datesThenMealsOrExercise)) {
                    $scope.datesThenMealsOrExercise[date.when] = [];
                }
                arr = $scope.datesThenMealsOrExercise[date.when];
                arr.push({
                    type: type,
                    plural: plural,
                    verb: verb,
                    name: date.name,
                    items: date.items
                });
            });
        }

        JsonGetter.get({q:'my-data.json'}, function(mne) {
            $scope.mealsAndExercise = mne; // raw
            // Marginally trasnformed for first view
            $scope.mealsOrExerciseThenDates = [
              {
                name:"Meals",
                plural:"items",
                verb:"consumed",
                data: mne.M
              },
              {
                name:"Exercise",
                plural:"exercises",
                verb:"burned",
                data: mne.E
              }
            ];
            $scope.datesThenMealsOrExercise = {};
            // Transformed quite a bit for second view
            insertItems(mne.M, "Meal", "items", "consumed");
            insertItems(mne.E, "Exercise", "exercises", "burned");
        });
        $scope.totCalories = function(toTotal){
            var totalKCal = 0;
            for(var i = 0; i < toTotal.length; i++){
                var item = toTotal[i];
                totalKCal += item.kcal;
            }
            return totalKCal;
        };
        $scope.abs = function(toAbs){
            return Math.abs(toAbs);
        }
    });

Or, take a look at the JSON it loads over HTTP

{
  "goal" : 1300,
  "M": [
    {
      "when": "2016-02-25",
      "name" : "snack",
      "items": [{
        "item": "Snickers bar", "kcal": 305
      }]
    },
    {
    "when": "2016-02-26",
    "name" : "Breakfast",
    "items": [
      {
        "item": "Nachos", "kcal": 223
      },{
        "item": "Dip", "kcal": 371
      },{
        "item": "Salsa", "kcal": 188        
    }]
  },
  {
    "when": "2016-02-26",
    "name" : "Lunch",
    "items": [{
      "item": "Steak", "kcal": 498
    },{
      "item": "Mash", "kcal": 212
    }]
  }
  ],
  "E": [
  {
    "when": "2016-02-26",
    "name" : "Gym",
    "items": [{
      "item": "Running Machine", "kcal": -210
    },{
      "item": "Step Machine", "kcal": -88
    },{
      "item": "Weights", "kcal": -80
    }]
  },
    {
      "when": "2016-02-25",
      "name" : "Swim",
      "items": [{
        "item": "42 laps", "kcal": -305
      }]
    }
  ]
}

Selling a Style of Angular

When I code Angular for demo purposes, I completely avoid:

  1. Any build technology
  2. HTML inside JavaScript (template style)
  3. JsFiddle-like services

I wish more people would too. It’s much easier to pick up or teach. Especially, if you are example-oriented like me.

Monitor application stability with Bugsnag to decide if your engineering team should be building new features on your roadmap or fixing bugs to stabilize your application.Try it free.

Topics:
angular ,mvc

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}