Join the Stack Overflow Community
Stack Overflow is a community of 6.7 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I'm trying to get to work angular.js, ui-router, and require.js and feel quite confused. I tried to follow this tutorial http://ify.io/lazy-loading-in-angularjs/. First, let me show you my code:

app.js =>

var app = angular.module('myApp', []);
app.config(function ($stateProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
    $stateProvider.state('home',
        {
            templateUrl: 'tmpl/home-template.html',
            url: '/',
            controller: 'registration'
            resolve: {
                deps: function ($q, $rootScope) {
                    var deferred = $q.defer(),
                        dependencies = ["registration"];
                    require(dependencies, function () {
                        $rootScope.$apply(function () {
                            deferred.resolve();
                        });
                    })
                    return deferred.$promise;
                }
            }
        }
    );
    app.lazy = {
        controller: $controllerProvider.register,
        directive: $compileProvider.directive,
        filter: $filterProvider.register,
        factory: $provide.factory,
        service: $provide.service
    };
});

Now in my registration.js I have following code:

define(["app"], function (app) {
    app.lazy.controller("registration" , ["$scope", function ($scope) {
        // The code here never runs
        $scope.message = "hello world!";
    }]);
});

everything works well, even the code in registration.js is run. but the problem is code inside controller function is never run and I get the error Error: [ng:areq] http://errors.angularjs.org/1.2.23/ng/areq?p0=registration&p1=not a function, got undefined

Which seems my code does not register controller function successfully. Any Ideas?

P.s. In ui-router docs it is said "If any of these dependencies are promises, they will be resolved and converted to a value before the controller is instantiated and the $routeChangeSuccess event is fired." But if I put the deferred.resolve(); from mentioned code inside a timeOut and run it after say 5 seconds, my controller code is run and my view is rendered before resolve, Strange.

share|improve this question
    
shouldn't it be return deferred.promise; instead of return deferred.$promise; in the resolve function? – sceid Dec 1 '14 at 22:53

Seems like I ran into the exact same problem, following the exact same tutorial that you did, but using ui-router. The solution for me was to:

  1. Make sure the app.controllerProvider was available to lazy controller script. It looked like you did this using app.lazy {...}, which a really nice touch BTW :)
  2. Make sure the lazy ctrl script uses define() and not require() I couldn't tell from your code if you had done this.

Here is my ui-router setup with the public app.controllerProvider method:

app.config(function ($stateProvider, $controllerProvider, $filterProvider, $provide, $urlRouterProvider) {

  app.lazy = {
    controller: $controllerProvider.register,
    directive: $compileProvider.directive,
    filter: $filterProvider.register,
    factory: $provide.factory,
    service: $provide.service
  };

  $urlRouterProvider.otherwise('/');

  $stateProvider

    .state('app', {
      url:'/',
    })

    .state('app.view-a', {
      views: {
        'page@': {
          templateUrl: 'view-a.tmpl.html',
          controller: 'ViewACtrl',
          resolve: {
            deps: function ($q, $rootScope) {
              var deferred = $q.defer();

              var dependencies = [
                'view-a.ctrl',
              ];

              require(dependencies, function() {
                $rootScope.$apply(function() {
                  deferred.resolve();
                });
              });

              return deferred.promise;
            }
          }
        }
      }
    });
});

Then in my lazy loaded controller I noticed that I had to use require(['app']), like this:

define(['app'], function (app) {

  return app.lazy.controller('ViewACtrl', function($scope){
     $scope.somethingcool = 'Cool!';
  });

});

Source on GitHub: https://github.com/F1LT3R/angular-lazy-load

Demo on Plunker: http://plnkr.co/edit/XU7MIXGAnU3kd6CITWE7

share|improve this answer

Changing you're state's url to '' should do the trick. '' is root example.com/, '/' is example.com/#/.

share|improve this answer
    
Actually, I have some other code that removes trailing slashes, so I think there would be no difference. On the other hand, I'm using html 5 routing mode. – Javad M. Amiri Aug 31 '14 at 9:05
    
Not sure if html 5 routing mode would effect it or not, but i don't think it would. As for your code that removes trailing slashes, do you mean it removes them from you're states url, a links href, or when the route is requested but before its handed to ui-router? – yelvert Aug 31 '14 at 9:16
    
For trailing slashes, I mean there is no difference between 'example.com/sample-url' and 'example.com/sample-url/'. There is nothing wrong with routing since the state is activated and it searches for the controller. My controller is not registered when the app is bootstrapped, rather after the state is activated. But, still it should work since it should be registered before the state asks for controller. – Javad M. Amiri Aug 31 '14 at 11:49
    
The dependencies mentioned there is speaking of things to be injected into the controller, not the controller itself. Also, notice, that in the tutorial you mention above (ify.io/lazy-loading-in-angularjs), they are using angular's built in router, but in your use case, you're using ui-router's $state, which may have already looked up the controller for a state before running it's resolves, since your controller comes from a resolve, then it does not exist the first time the state is hit. – yelvert Aug 31 '14 at 20:56

I came to give my 2 cents. I saw you already resolved it, I just want to add a comment if someone else have a similar problem.

I was having a very similar issue, but I had part of my code waiting for the DOM to load, so I just called it directly (not using the "$(document).ready") and it worked.

$(document).ready(function() { /*function was being called here*/ });

And that solved my issue. Probably a different situation tho but I was having the same error.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.