0

I am relatively new to angularJS, I am trying to set up a page where inturn multiple pages are called depending upon the selection made previously. All the pages have their own controller, so I am trying to set the controller and view src through the javascript and using them in HTML tags.

Following is what I am doing:
HTML page:

<div ng-if="sidebarName=='sidebar-device-wire'">
        <div ng-controller="getSidebarCtlr">    
            <div ng-include src="sidebarSrc"></div>
        </div>
    </div>

javascript:

$scope.sidebarSrc="views/sidebars/sidebar-device.html";
$scope.sidebarCtlr="SidebarDeviceCtrl";

$scope.getSidebarCtlr = function(){return $scope.sidebarCtlr;}

For some reason though, this does not work. i can get the HTML page but the controller is not being called. Can anyone please tell me what I am doing wrong?

Yash shah
  • 1
  • 2
  • 3
    don't do this. use `ngRoute` or a well tested 3rd party replacement like `uiRouter` instead. – Claies Dec 20 '15 at 15:46
  • There is a constraint, I cannot use APIs, I have to work with what I got. – Yash shah Dec 20 '15 at 15:52
  • 1
    I second @Claies. Use uiRouter. – Tarun Dugar Dec 20 '15 at 15:53
  • 1
    neither `ngRoute` nor `uiRouter` are APIs. – Claies Dec 20 '15 at 15:59
  • you can't invoke a controller by referring to it's name in a variable. What you are trying to do *might* work if you interpolated the function output, i.e. `ng-controller="{{getSideBarCtrlr}}"`, but this is very abnormal, and recreating a major framework feature like this is challenging even for people very familiar with the framework. `ngRoute` is a core module designed to do what you are trying to do. – Claies Dec 20 '15 at 16:07
  • @Claies Thanks, I am trying to understand ng-route and ui-route. I think I might be able to learn it and apply. If you have easy example explaining, please provide those. I really appreciate your quick responses/help ! – Yash shah Dec 20 '15 at 16:22
  • the official example really does a great job: https://docs.angularjs.org/api/ngRoute/service/$route#example/ It shows how to create multiple controllers, how to pass URL parameters, and how to resolve dependencies. – Claies Dec 20 '15 at 16:26

2 Answers2

0

I would also recommend to use ngRoute or ui.router because there are many features that aren't easy to implement from scratch (like named views, nested views / nested states or resolves) and these modules are well tested.

Not sure why your controller isn't running but I guess that the expression of the controller is evaluated before your controller that is setting the name is running. So it will be always undefined at compile time.

But if you really like to implement a very basic router you could do it like in the following demo (or in this fiddle).

Update 21.12.2015

Here are some router examples that I wrote for other SO questions:

  • simple ui.router example - jsfiddle
  • more complex nested state example ui.router - jsfiddle
  • dynamic link list with ngRoute - jsfiddle

Please also have a look at ui.router github pages to learn more about it.

angular.module('simpleRouter', [])
  .directive('simpleView', simpleViewDirective)
  .provider('simpleRoutes', SimpleRoutesProvider)
  .controller('MainController', MainController)
  .controller('HomeController', HomeController)
  .config(function(simpleRoutesProvider) {
    simpleRoutesProvider.state([{
      url: '/',
      templateUrl: 'home.html',
      controller: 'HomeController'
    }, {
      url: '/view1',
      templateUrl: 'view1.html'
    }, {
      url: '/view2',
      templateUrl: 'view2.html',
      controller: function($scope) {
       $scope.test = 'hello from controller'
      }
    }]);

    simpleRoutesProvider.otherwise('/');
  })

function HomeController($scope) {
 $scope.hello = 'hello from home controller!!';
 console.log('home controller started')
}

function MainController($scope) {
   $scope.hello = 'Main controller test';
}

function simpleViewDirective() {
  return {
    restrict: 'EA',
    scope: {},
    template: '<div ng-include="templateUrl"></div>',
    controller: function($scope, $location, $controller, simpleRoutes) {
     var childControllerInst;
      $scope.templateUrl = simpleRoutes.currentRoute.templateUrl || simpleRoutes.otherwise.templateUrl;
      
      $scope.$watch(function() {
        return $location.path();
      }, function(newUrl) {
        //console.log(newUrl)
        $scope.templateUrl = simpleRoutes.changeRoute(newUrl);
        
        childControllerInst = $controller(simpleRoutes.currentRoute.controller || function() {}, {$scope: $scope});
        
      });
      
      $scope.$on('$destroy', function() {
       childControllerInst = undefined;
      })
    },
    link: function(scope, element, attrs) {

    }
  }
}

function SimpleRoutesProvider() {
  var router = {
    currentRoute: {
      templateUrl: ''
    },
    states: [],
    otherwise: {},
    changeRoute: function(url) {
      var found = false;
      angular.forEach(router.states, function(state) {
        //console.log('state', state);
        if (state.url == url) {
          router.currentRoute = state;
          found = true;
        }
      });

      if (!found) router.currentRoute = router.otherwise;
      //console.log(router.currentRoute);
      return router.currentRoute.templateUrl;
    }
  };

  this.state = function(stateObj) {
    router.states = stateObj;
  };

  this.otherwise = function(route) {
   angular.forEach(router.states, function(state) {
     if (route === state.url ) {
      router.otherwise = state;   
      }
    });
    
    //console.log(router.otherwise);
  };

  this.$get = function simpleRoutesFactory() {
    return router;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="simpleRouter" ng-controller="MainController">
  <script type="text/ng-template" id="home.html">home route {{hello}}</script>
  <script type="text/ng-template" id="view1.html">view1</script>
  <script type="text/ng-template" id="view2.html">view2 {{test}}</script>

  <div simple-view="">
  </div>
  <a href="#/">home</a>
  <a href="#/view1">view1</a>
  <a href="#/view2">view2</a>
  <br/>
  {{hello}}
</div>
AWolf
  • 8,770
  • 5
  • 33
  • 39
0

What's that code means? $scope.getSidebarCtlr = function(){return $scope.sidebarCtlr;}

the ng-directive requires a Controller name, its argument type is string and you cannot pass a simple function, you need to register a valid controller associating it to a module via the controller recipe.

https://docs.angularjs.org/guide/controller

angular.module('test', []).controller('TestCtrl', function($scope) {
  $scope.greetings = "Hello World";
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<section ng-app="test">
  <article ng-controller="TestCtrl">{{ greetings }}</article>
</section>
Hitmands
  • 13,491
  • 4
  • 34
  • 69