1

I have a component() which injects a nav. When I try to include the controller inside this component like so, I get an error.

inside nav.html

<nav class="navbar navbar-inverse navbar-fixed-top">
  <div class="container">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Demo</a>
    </div>
    <div id="navbar" class="collapse navbar-collapse" ng-controller="MainMenuController">
      <ul class="nav navbar-nav">
        <li ng-class="{ active: isActive('') }"><a href="./">home</a></li>
        <li ng-class="{ active: isActive('/skus') }"><a href="sku.html">sku</a></li>
        <li ng-class="{ active: isActive('/phones') }"><a href="phone.html">phone</a></li>
      </ul>
    </div><!--/.nav-collapse -->
  </div>
</nav>


inside component.js

angular.
module('mainMenu').
component('mainMenu', {
  templateUrl: 'app/core/nav/nav.html',
  controller: 'MainMenuController', ['$scope', '$location', 
    function NavController($scope, $location) {
        $scope.isActive = function (viewLocation) { 
          var p1 = $location.path();
          var p2 = '/' + p1.split("/")[1]; // split string from '/';
          if(p2=='/undefined') p2 = '';
          return viewLocation === p2;
        }
    }
  ]
});

But if I write a separate controller like this everything works fine. What am I doing wrong with component() and should I not be including the controller in component() for best practice?

angular.
module('mainMenu').
component('mainMenu', {
  templateUrl: 'app/core/nav/nav.html',
});


angular.
module('mainMenu').
controller('MainMenuController', ['$scope', '$location', 
      function NavController($scope, $location) {
        //this.navs = Nav;
        $scope.isActive = function (viewLocation) {
          var p1 = $location.path();
          var p2 = '/' + p1.split("/")[1]; // split string from '/';
          if(p2=='/undefined') p2 = '';
          return viewLocation === p2;
        };
      }
]);


I changed my component to this

angular.
module('mainMenu').
component('mainMenu', {
  templateUrl: 'app/core/nav/nav.html',
  controller: ['$scope', '$location', 
    function MainMenuController($scope, $location) {
      //this.navs = Nav;
      $scope.isActive = function (viewLocation) {
        var p1 = $location.path();
        var p2 = '/' + p1.split("/")[1]; // split string from '/';
        if(p2=='/undefined') p2 = '';
        return viewLocation === p2;
      };
    }
  ]
});

getting error Error: [ng:areq] http://errors.angularjs.org/1.5.8/ng/areq?p0=MainMenuController&p1=not%20a%20function%2C%20got%20undefined N



Fix: By cleaning up the module and component titles and making them unique, removing ng-controller from the template; Neal Hamilton's answer below fixed my original question.

13
  • 1
    Either you specify a controller name, or you specify a controller function, but not both. Remove 'MainMenuController', . Also, please never, ever again ask a question just saying "I have an error". Post the exact and complete error message instead. Commented Oct 7, 2016 at 16:45
  • 2
    "I get an error." what error?? Commented Oct 7, 2016 at 16:47
  • Changed my question with error output Commented Oct 7, 2016 at 16:50
  • 1
    In your first example, you are naming your component to be the same as your module which is a no-no. Also, all the information you seek is documented in the angular documentation for components. Commented Oct 7, 2016 at 16:51
  • 1
    so again, this latest update verifies my theory. You have an ng-controller reference inside the template. the controller is being supplied to the whole template, and then you are trying to re-bind the same controller to an element inside the template. It may work when you declare the controller outside the template, but it probably won't work the way you expect, as you actually have two instances of the same controller object. It definitely won't work at all if you only declare the controller as belonging to the component. Commented Oct 7, 2016 at 18:04

1 Answer 1

5

this is my preference when adding controllers...

MainMenuController.$inject = ['$scope', '$location'];
function MainMenuController($scope, $location) {}

angular.module('menu').component('mainMenu', {
    controller: MainMenuController,
    controllerAs: 'MainMenuController',
    templateUrl: 'app/core/nav/nav.html'
});

the style you're trying to do with dependencies inline...

angular.module('menu').component('mainMenu', {
    controller: ['$scope', '$location', function($scope, $location) {}],
    controllerAs: 'MainMenuController',
    templateUrl: 'app/core/nav/nav.html'
});

Difference being that you had the ControllerAs String with the controller declaration. You should be using the controllerAs: "NameForController" property to name the controller.

Good Luck!

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

8 Comments

when I used your first answer I still get an Error: [ng:areq] http://errors.angularjs.org/1.5.8/ng/areq?p0=MainMenuController&p1=not%20a%20function%2C%20got%20MainMenuController N/
That error is indicating that you are passing a string "MainMenuController" and not a function to the controller property.
but I have it set up exactly as yours.
I think I forgot a comma after controllerAs: 'MainMenuController' , <--
That fiddle is working code like the one from my first example. hopefully that will help sort things out.
|

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.