简体   繁体   中英

Using controllers added by routes to declare $scope variables in Angular JS?

My application is an SPA. It includes templates based on route. It also declares a scope variable based on route. I accomplished that last part by setting a controller for each route on the .config service.

This is my config...

spa.config(function($routeProvider) {
    $routeProvider
            .when('/home', {
                templateUrl: '/partials/home.html',
                controller: 'homeController'
            })
            .when('/about', {
                templateUrl: '/partials/about.html',
                controller: 'aboutController'
            })
            .when('/skills', {
                templateUrl: '/partials/skills.html',
                controller: 'skillsController'
            })
            .when('/experience', {
                templateUrl: '/partials/experience.html',
                controller: 'experienceController'
            })
            .when('/resume', {
                templateUrl: '/partials/resume.html',
                controller: 'resumeController'
            })
            .when('/contact', {
                templateUrl: '/partials/contact.html',
                controller: 'contactController'
            })
            .otherwise({
                redirectTo: '/home'
            });
});

These are all my controllers...

/*Template Controllers*/

var homeController = spa.controller("homeController", function($scope) {
    $scope.currentLink = "home";
})

var aboutController = spa.controller("aboutController", function($scope) {
    $scope.currentLink = "about";
})

var skillsController = spa.controller("skillsController", function($scope) {
    $scope.currentLink = "skills";
})

var experienceController = spa.controller("experienceController", function($scope) {
    $scope.currentLink = "experience";
})

var resumeController = spa.controller("resumeController", function($scope) {
    $scope.currentLink = "resume";
})

var contactController = spa.controller("contactController", function($scope) {
    $scope.currentLink = "contact";
})

/*Dynamic CSS Linking*/

var cssController = spa.controller("cssController", function($scope) {
    this.fileName = $scope.currentLink;
});

/*Navigation Controller*/

var navigationController = spa.controller("navigationController", function($scope) {
    this.checkCurrent = function(checkValue) {
        return $scope.currentLink == checkValue;
    }
    this.linkValues = [
    {linkContent: "Home", linkValue: "home"},
    {linkContent: "About", linkValue: "about"},
    {linkContent: "Skills", linkValue: "skills"},
    {linkContent: "Experience", linkValue: "experience"},
    {linkContent: "Resume", linkValue: "resume"},
    {linkContent: "Contact", linkValue: "contact"}
    ];
});

And this is my HTML

<!DOCTYPE html>
<html  ng-app="spa">
    <head ng-controller="cssController as cssCtrl">
        <title>
            Allen Hundley
        </title>
        <!--Favicon-->
        <link rel="shortcut icon" href="http://allenhundley.com/images/favicon.ico" type="image/x-icon">
        <link rel="icon" href="http://allenhundley.com/images/favicon.ico" type="image/x-icon">
        <!--End Favicon-->
        <!--CSS-->
        <link rel="stylesheet" type="text/css" href="http://allenhundley.com/css/base.css">
        <link rel="stylesheet" type="text/css" ng-href="http://allenhundley.com/css/partials_css/{{ cssCtrl.fileName + '.css' }}">
        <!--End CSS-->
        <!--JavaScript Sources-->
        <script type="text/javascript" src="http://allenhundley.com/resources/angular.js"></script>
        <script type="text/javascript" src="http://allenhundley.com/resources/angular-route.js"></script>
        <!--End JavaScript Source-->
        <!--JavaScript-->
        <script type="text/javascript" src="http://allenhundley.com/js/modules.js"></script>
        <script type="text/javascript" src="http://allenhundley.com/js/services.js"></script>
        <script type="text/javascript" src="http://allenhundley.com/js/controllers.js"></script>
        <script type="text/javascript" src="http://allenhundley.com/js/directives.js"></script>
        <!--End JavaScript-->
    </head>
    <body>
        <div id="navigation">
            <div id="link_wrapper" ng-controller="navigationController as navCtrl">
                <navigation-links></navigation-links>
            </div>
        </div>
        <div ng-view id="wrapper"></div>
    </body>
</html>

All controllers and factories are applied to the spa module.

The links in my page link to new routes. That part works perfectly. Additionally the controllers which are added by the route declare a scope variable which is later grabbed by some other controllers.

The first place this scope variable is used is in the cssController . The intent of this controller is to dynamically link a css file which will pertain to the HTML template.

The second place this scope variable is used is in the navigationController . Although you can't see it, in each link in the element directive there is a link to navigationController 's checkCurrent function. This function returns a boolean that affects whether the link has CSS applied to it which makes it the "active" link.

The problem here is that either my scope variable isn't getting declared, or I'm not accessing it correctly.

How do I accomplish this?

Are you intent to share currentLink across all controllers in your app? If it is, then there are couple ways of doing it.

The first way is using $rootScope . The $scope you use is not shared among controllers, they are different instance, each bound to a view that the controller is declared on. $rootScope is your top level $scope which only have one instance per app, and you can conveniently inject it into all controllers.

var homeController = spa.controller("homeController", function($scope, $rootScope) {
    $rootScope.currentLink = "home";
})

If you don't have too much data that needs to be shared in global scope (which you shouldn't), you can use this approach. Or even make an object to hold it if you have a couple more.

$rootScope.data = {};

The second way is to use a service. This is more "formal" way of sharing data between selected controllers. Controllers that needs the data will inject the service, and controllers that don't will not aware of it. There are many guides which teach you how to setup a service, here is just one of the way.

spa.service('Navigation', function(){
    this.currentLink= null;

    // some people prefer get and set method here
    // var currentLink;
    // this.getLink = function() {return currentLink;}
    // this.setLink = function(input) {currentLink = input;}

    // and some uses an object wrapper for binding
    // this.data = {currentLink: null};

    // depends on which one suits your need and preference
});

In controller you inject them and use it like $rootScope

var homeController = spa.controller("homeController", function($scope, Navigation) {
    Navigation.currentLink = "home";
})

Edit: In this case where you are trying to match by route name only, you can just use $location.path() to determine the current path.

jsbin

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM