angularjs - Sharing async model data between controllers -


warning: long question

i new angular , i've gone through few tutorials , examples such official tutorial on angularjs website. recommended way data app , share data between controllers seems clear. create service shared controllers makes asynchronous request server data in json format.

this great in theory, , seems fine in extremely simple examples show 1 controller, or when controllers don't share logic depends on shared data. take following example of simple budget application based on yearly income , taxes:

create app dependency on ngresource:

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

netincomectrl controller handles income , tax items, , calculates net income:

app.controller('netincomectrl', function ($scope, budgetdata) {     var categorytotal = function (category) {         var total = 0;         angular.foreach(category.transactions, function (transaction) {             total += transaction.amount;         });         return total;     };      $scope.model = budgetdata.get(function (model) {         $scope.totalincome = categorytotal(model.income);         $scope.totaltaxes = categorytotal(model.taxes);     });      $scope.netincome = function () {         return $scope.totalincome - $scope.totaltaxes;     }; }); 

budgetdata service uses $resource retrieve json data server:

app.factory('budgetdata', function ($resource) {     return $resource('data/budget.json'); }); 

budget.json contains json data returned server:

{     "income": {         "transactions": [             {                 "description": "employment",                 "amount": 45000             },             {                 "description": "investments",                 "amount": 5000             }         ]     },      "taxes": {         "transactions": [             {                 "description": "state",                 "amount": 5000             },             {                 "description": "federal",                 "amount": 10000             }         ]     }, } 

then on screen have 2 repeaters show income , tax items (which can edit), , net income calculated , displayed.

this works great, , standard approach i've seen used in tutorials. however, if add 1 more controller depends on of same data , logic, begins unravel:

expensesctrl controller expenses in end calculate surplus (net income - expenses):

app.controller('expensesctrl', function ($scope, budgetdata) {     var categorytotal = function (category) {         var total = 0;         angular.foreach(category.transactions, function (transaction) {             total += transaction.amount;         });         return total;     };      $scope.model = budgetdata.get(function (model) {         $scope.totalincome = categorytotal(model.income);         $scope.totaltaxes = categorytotal(model.taxes);         $scope.totalexpenses = categorytotal(model.expenses);     });      $scope.netincome = function () {         return $scope.totalincome - $scope.totaltaxes;     };      $scope.surplus = function () {         return $scope.netincome() - $scope.totalexpenses;     }; }); 

budget.json adds expenses data:

"expenses": {     "transactions": [         {             "description": "mortgage",             "amount": 12000         },         {             "description": "car payments",             "amount": 3600         }     ] } 

then on separate part of screen have section uses controller , uses repeater show expense items, , re-displays net income, , shows resulting surplus.

this example works, there several problems (questions) it:

1) in example i've managed keep of controller's logic out of callback function, controllers start out in callback because depends on model being loaded. understand nature of javascript, angular supposed reduce need of these callbacks, , doesn't seem clean. reason able take of logic out of callbacks here because of magic angular under hood substitute fake object model until model gets loaded. since 'magic' not intuitive, it's hard tell if code work expected.

is there consistent way people deal this? don't want elaborate solution makes 101 intro app complicated. there simple , standard approach restructuring code somehow avoid many callbacks , make code more intuitive?

2) have bunch of repeated logic. categorytotal , netincome logic should in 1 place, , shared between controllers. these controllers used in separate parts of screen, can't use scope inheritance. when using scope inheritance there problems, because child controller's scope can't depend on parent scope's model being loaded when own model loaded.

the categorytotal logic helper function isn't tied directly model, don't know put generic helper functions in angular. netincome directly depend on model , needs in scope, possible add service or model. however, service should concerned retrieving model server, , model should contain data, , anemic possible. also, seems kind of logic belongs in controller. there standard way deal this?

3) every time service called fetch data, http request server, though data same every time. model should cached after first request, there 1 request made.

i realize handle in service. store model local variable , check variable see if data exists before making request. seems odd none of tutorials read mentioned this. also, i'm looking standard 'angular' way of dealing it.

sorry incredibly long post. keep app @ 101 intro level, , not complicated areas if possible. i'm hoping there standard 'angular' way deal these problems have not come across yet.

thanks in advance!

this how it. create service handles data, , if changed broadcasts messages controllers. initial data can gotten budgetdata.data. if changes data

.service("budgetdata", function($http, $rootscope) {   var this_ = this, data;    $http.get('wikiarticles/categories', function(response) {     this_.set(response.data);   }    this.get = function() {     return data;   }    this.set = function(data_) {     data = data_;     $rootscope.$broadcast('event:data-change');   }  }); 

in controller need listen events, , update scope variables accordingly. can use in many controllers want.

$rootscope.$on('event:data-change', function() {   $scope.data = budgetdata.get(); }  $scope.update = function(d) {   budgetdata.set(d); } 

Comments

Popular posts from this blog

Android layout hidden on keyboard show -

google app engine - 403 Forbidden POST - Flask WTForms -

c - Why would PK11_GenerateRandom() return an error -8023? -