WARNING: Long description of what i'm actually doing.
I have a Single Page Application with the following layout:
As you can see, it's a layout comprised by tabs and each tab is a directive with it's own controller (and scope). All the form it's a directive itself, comprised by small directives, contained as tabs, as follows:
main.html
<div class="container-fluid">
<div class="evaCont">
<div class="eva_title">Form</div>
<form id="mainForm" ng-submit="submit()">
<div class="col-xs-12">
<input type="submit" class="btn btn-primary" value="Save"/>
</div>
<div class="tab col-xs-12">
<tabset justified="true">
<tab heading="Data section 1">
<ds1></ds1>
</tab>
<tab heading="Data section 2">
<ds2></ds2>
</tab>
<tab heading="...">
<ds3></ds3>
</tab>
</tabset>
</div>
</form>
</div>
</div>
To fill the SPA with data i'm calling a REST API to get it (JSON). I've made a service for that purpose:
'use strict';
angular.module('frontendApp').factory('backendService', function($resource, $location){
var objBackend = {};
objBackend.query = function(id) {
var data = $resource('http://localhost:9010/API/:dataID', {dataID: id}, {
query: {
method: 'GET',
headers: {'token': '1588526404200542348177491835893601182229853'}
}
});
var dataForFrontEnd = data.query().$promise.then(function(d){
console.log(d);
return d;
},
function(error){
...
});
return dataForFrontEnd;
}
return objBackend;
});
I have a customized version of query method of $resource for manage success and failure of the REST call (and for sending the custom 'token' header). My AngularJS app requires the data of the API and then i set it in the scope of the Main controller. I'm doing that because, if i inject the service and call the query() method Angular will call the API n times for each directive, returning exactlly the same object. Instead of that, i call it only one time in the application load and share the JSON data between all controllers (one controller for each tab).
Main Form Controller:
'use strict';
angular.module('frontendApp')
.controller('MainCtrl', function ($scope, $routeParams, data, datepickerPopupConfig) {
$scope.data = data;
datepickerPopupConfig.showButtonBar = false;
$scope.submit = function(){
console.log($scope.data.val1);
};
});
app.js:
'use strict';
angular
.module('frontendApp', [
'ngAnimate',
'ngAria',
'ngCookies',
'ngMessages',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch',
'ui.bootstrap'
])
.config(function ($routeProvider) {
$routeProvider
.when('/API/:dataID', {
templateUrl: 'main/directives/main.html',
controller: 'MainCtrl',
resolve: {
data: function(backendService, $route){
var id = $route.current.params.dataID;
return backendService.query(id);
}
}
})
.otherwise({
redirectTo: '/notfound'
});
});
Directive 1 (shows how i am binding the data, based on the parent scope):
JS (Directive):
'use strict';
angular.module('frontendApp')
.directive('ds1', function($http){
return {
restrict: 'E',
replace: true,
scope: true,
templateUrl: 'basic/directives/basic.html',
controller: 'ds1'
};
});
JS (Controller):
'use strict';
angular.module('frontendApp')
.controller('ds1', function ($scope) {
var data = $scope.data;
$scope.val1 = data.val1;
$scope.val2 = data.val2;
$scope.val3 = data.val3;
//Datepicker
$scope.dpOpened = {
val1: false,
val2: false,
val3: false
};
$scope.open = function($event, opened) {
$event.preventDefault();
$event.stopPropagation();
$scope.dpOpened[opened] = true;
};
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1
};
$scope.format = 'yyyy-MM-dd';
//Datepicker
});
HTML:
<div class="container-fluid">
<h4>Data section 1</h4>
<div class="form-group">
<div class="col-xs-6 col-sm-3">
<label for="value1">Value 1/label>
<select id="value1" class="form-control" ng-model="val1" ng-required="true">
<option value="1">X</option>
<option value="2">Y</option>
<option value="3">Z</option>
</select>
</div>
<div class="col-xs-6 col-sm-3">
<label for="value2">Val 2</label>
<select id="value2" class="form-control" ng-model="val2" ng-required="true">
<option value="A">A</option>
<option value="B">B</option>
</select>
</div>
<div class="col-xs-6 col-sm-3">
<label for="value3">Value 3</label>
<input id="value3" type="text" ng-model="val3" ng-required="true" disabled class="form-control"/>
</div>
</div>
</div>
PROBLEM (and question): When i click in the submit button to send the form data AngularJS doesn't recognize neither of changed values. I think that my problem is the scope. When i copy the values of my main object into values of the directive scope i cannot see the changes that the user made in the form.
Question: Based in my layout and in my description, what is the right way to share the data between all directives AND get the changes, knowing that i'm using ng-model?
Remember that i'm not injecting my service because i don't want to call my API every time for each directive, instead i want to have a single API-Call and the data returned in the parent controller, but sharing it in the child controllers.
Thanks in advance