0

Im pretty new to Angular.js and trying to implement it on my Node.js app.

Ive had success creating an RESTful API using angular for a single controller but now would like to use two or more controllers on a single DOM.

Specifically, I would like to..

1) Use angular to load a global scope for the DOM template containing things like site title, navigation, and metadata, all of which will be loaded into the head, header, and footer. The scope would be pulled using a GET request to my Node server.

2) Use angular to load the scope for a given page. This would be on a case-by-case basis for each page. The simple case being to load the scope into the template.

I have succeeded in doing both (1) and (2) separately, but combining them throws an error.

Here is my complete template (actually loaded in parts by Node):

Head - containing ng-controller="configCtrl" for global configuration scope

<html ng-app="angular" ng-controller="configCtrl" ><head> 

<meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
<title>{{context.title}}</title>
<meta name="description" content="{{context.description}}">
<meta name="author" content="{{context.author}}">

<!-- Angular -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>

</head><body><div id="wrapper" >

Body - containing ng-controller="testCtrl" for this particular page scope

<div class="container" ng-controller="testCtrl">    
    <div class="gutter col hidden-xs">&nbsp;</div>
    <div class="content col" >

        <div class="py80">

            <h1>{{context.test}}</h1>

        </div>

    </div> 
    <div class="gutter col hidden-xs">&nbsp;</div>
</div> 

<!-- ANGULAR CONTROLLER FOR THIS PAGE -->
<script src="/public/js/angular/test_controller.js"></script> 

Footer - includes the link to controller for global scope

<footer id="footer" ></footer>
</div></body></html> <!-- close tags-->

<!-- ANGULAR CONTROLLER FOR GLOBAL CONFIGURATION SCOPE -->
<script src="/public/js/angular/config_controller.js"></script>

Here is my Angular controller for the "configuration scope"

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

app.controller('configCtrl', function($scope, $http) {

    console.log("config controller");

    $http.get('/config').then(function(response){ 

        console.log(response.data);

        $scope.context = response.data;

    });

});

Here is my Angular controller for the page scope

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

app.controller('testCtrl', function($scope, $http) {

    console.log("test controller");

    $http.get('/test').then(function(response){ 

        console.log(response.data);

        $scope.context = response.data;

    });

});

I have some server-side controllers returning data back to angular, as mentioned, they each work when used independently but using them together (as shown above) throws the following client-side error:

 angular.js:13920 Error: [ng:areq] http://errors.angularjs.org/1.5.8/ng/areq?p0=testCtrl&p1=not%20a%20function%2C%20got%20undefined
 at angular.js:38
 at sb (angular.js:1892)
 at Pa (angular.js:1902)
 at angular.js:10330
 at ag (angular.js:9451)
 at p (angular.js:9232)
 at g (angular.js:8620)
 at g (angular.js:8623)
 at g (angular.js:8623)
 at g (angular.js:8623)

Any suggestions?

2 Answers 2

2

The problem is you are initializing the app twice. Do this only once:

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

And you’ll be fine. Best practice is to separate that line out into another file entirely (like 'app-initialize.js') and then, you can just do:

angular.module('angular').controller(...);

in all of your files.

Sign up to request clarification or add additional context in comments.

Comments

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

You're calling this line twice (based on your example) which will create a module called 'angular' twice.

Also, instead of using a controller for the configuration, you can create a factory or service and inject it into any controller that needs it. (roughly:)

var app = angular.module('someApp', []);
app.controller('testCtrl', function($scope, $http, configFactory) {

    $scope.getConfig = function() {
        configFactory.getConfig()
        .success(function (someConfig) {
            console.log(someConfig);
        });
    }

    $scope.getConfig();

    console.log("test controller");
    $http.get('/test').then(function(response){ 
        console.log(response.data);
        $scope.context = response.data;
    });

});
app.factory('configFactory', ['$http', function($http) {
    var getConfig = function() { 
        return $http.get('/config');
    }
    return getConfig;
}]);

Alternatively, you can create a configuration module and pass that as a dependency.

var config = angular.module('config', []).constant('config', { 'something': 2 });
...

var app = angular.module('someApp', ['config']);
...

1 Comment

ah! thank you for the solution and tip on best practice!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.