0

I am tryingto make a service that will allow me to manipulate variables outside ng-view. I made a service with factory, but I am at a loss how to transport variables from child-controller to parent (at least, this is the method I have been able to find by reading q&a's here on SO).

For example I would like to be able to manipulate {{ siteName }}, which is located outside ng-view from my articleCtrl controller.

This is what I did:

var blogApp = angular.module('blogApp', [
    'ngRoute',
    'ngSanitize',
    'blogCtrl'
]);

blogApp.config(['$routeProvider', '$locationProvider',
    function($routeProvider, $locationProvider) {
        $routeProvider.
            when('/page', {
                templateUrl: '/angular_blog/assets/templates/page.html',
                controller: 'pageCtrl'
            }).
            when('/page/:pagePermaLink', {
                templateUrl: '/angular_blog/assets/templates/page.html',
                controller: 'pageCtrl'
            }).
            when('/article/:articlePermaLink', {
                templateUrl: '/angular_blog/assets/templates/article.html',
                controller: 'articleCtrl'
            }).
            otherwise({
                redirectTo: '/page/404',
                templateUrl: '/angular_blog/assets/templates/404.html',
                controller: 'pageCtrl'
            });
        $locationProvider.html5Mode(true);
    }]);

blogApp.factory('templateService', function() {
    return {
        siteName:'',
        tagline:'',
        pageName:''
    };
});

function articleCtrl($scope, templateService) {
   $scope.template = templateService;
}

function templateCtrl($scope, templateService) {
   $scope.template = templateService;
}

var templateCtrl = angular.module('templateCtrl', []);
var blogCtrl = angular.module('blogCtrl', []);

blogCtrl.controller('articleCtrl', ['$scope', '$routeParams', '$http', 'templateService',
function($scope, $routeParams, $http, templateService) {
    $scope.siteName = "Something awesomediculous";
}]);

blogCtrl.controller('pageCtrl', ['$scope', '$routeParams', '$http',
function($scope, $routeParams, $http) {
    // ...
}]);

blogApp.controller('templateCtrl', function($scope, templateService) {
    // ...
});
<!DOCTYPE html>
<html lang="en" data-ng-app="blogApp" data-ng-controller="templateCtrl">
<head>
 <meta charset="UTF-8">
 <title>{{ pageName + " - " + siteName }}</title>

 <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
 <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-route.min.js"></script>
 <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular-sanitize.min.js"></script>

 <base href="/angular_blog/">

</head>
<body>

 <header>
  <h1>{{ siteName }}</h1>
  <p>{{ tagline }}</p>
 </header>

 <main id="content" data-ng-view></main>

</body>
</html>
Brian Emilius
  • 717
  • 1
  • 8
  • 31

2 Answers2

1

You could move the siteName property to templateCtrl which will then be available across all views.

blogApp.controller('templateCtrl', function($scope, templateService) {

   // this is important as updates from child will not take effect if done on primitives
   $scope.site = {};
   $scope.site.siteName = "Something awesomediculous";
});
Liam
  • 2,837
  • 23
  • 36
  • Okay, I might not simply understand the workflow here then, but doesn't this do the exact opposite of what I want? In my question I ask how to do it _from articleCtrl_ . Moving the variable definition line to templateCtrl makes it non-dynamic in this template-model, or no? – Brian Emilius Jul 28 '15 at 20:13
  • Anything from templateCtrl is inherited to child controller and any updates to variable from articleCtrl will update the parent. So for instance if the siteName is updated from articleCtrl and the view is changed then it will be reflected in the new ctrl as it also inherits the same variable. – Liam Jul 28 '15 at 20:17
  • Aaaah okay, then I think I get it! Thank you :) – Brian Emilius Jul 28 '15 at 20:23
  • Okay, I tried what you wrote, and when I then do `$scope.siteName = "something";` in articleCtrl, nothing happens. – Brian Emilius Jul 28 '15 at 20:29
  • you have to use the object $scope.site = {}; as primitives will not work. check this link http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs?rq=1 – Liam Jul 28 '15 at 20:30
1

You forgot to bind the service to your scope where you are supposed to do it, in your templateCtrl.

Also if you have $scope.template.myname you should use {{template.name}}.

See working code below.

Btw, there seems to be some unnecessary functions in your code

var blogApp = angular.module('blogApp', [
    'ngRoute',
    'ngSanitize',
    'blogCtrl'
]);

blogApp.config(['$routeProvider', '$locationProvider',
    function($routeProvider, $locationProvider) {
        $routeProvider.
            when('/page', {
                templateUrl: '/angular_blog/assets/templates/page.html',
                controller: 'pageCtrl'
            }).
            when('/page/:pagePermaLink', {
                templateUrl: '/angular_blog/assets/templates/page.html',
                controller: 'pageCtrl'
            }).
            when('/article/:articlePermaLink', {
                templateUrl: '/angular_blog/assets/templates/article.html',
                controller: 'articleCtrl'
            }).
            otherwise({
                redirectTo: '/page/404',
                templateUrl: '/angular_blog/assets/templates/404.html',
                controller: 'pageCtrl'
            });
        $locationProvider.html5Mode(true);
    }]);

blogApp.factory('templateService', function() {
    return {
        siteName:'mysitename',
        tagline:'mytagline',
        pageName:'mypagename'
    };
});

function articleCtrl($scope, templateService) {
   $scope.template = templateService;
}

function templateCtrl($scope, templateService) {
   $scope.template = templateService;
}

var templateCtrl = angular.module('templateCtrl', []);
var blogCtrl = angular.module('blogCtrl', []);

blogCtrl.controller('articleCtrl', ['$scope', '$routeParams', '$http', 'templateService',
function($scope, $routeParams, $http, templateService) {
    $scope.siteName = "Something awesomediculous";
}]);

blogCtrl.controller('pageCtrl', ['$scope', '$routeParams', '$http',
function($scope, $routeParams, $http) {
    // ...
}]);

blogApp.controller('templateCtrl', function($scope, templateService) {
    // ...
// added this line:
   $scope.template = templateService;
});
<!DOCTYPE html>
<html lang="en" data-ng-app="blogApp" data-ng-controller="templateCtrl">
<head>
 <meta charset="UTF-8">
 <title>{{ pageName + " - " + siteName }}</title>

 <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
 <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-route.min.js"></script>
 <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular-sanitize.min.js"></script>

 <base href="/angular_blog/">

</head>
<body>

 <header>
  <h1>{{ template.siteName }}</h1>
  <p>{{ template.tagline }}</p>
 </header>

 <main id="content" data-ng-view></main>

</body>
</html>
Sander_P
  • 1,787
  • 1
  • 13
  • 37