1

In our application we use the "controller as" syntax:

<div class="workspace-header" ng-controller="LoginController as loginCtl">

To define the LoginController, we define it as a TypeScript class:

class LoginController {
    // variables here

    constructor($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService) {
        // set variables

        this.$rootScope.$on(AUTH_EVENTS.logoutSuccess, () => {
            this.logout();
        });
    }

    public login(credentials: any): void {
        this.AuthService.login(credentials).then(() => {
            // login success
        }, () => {
            // login failed
        });
    }

    public logout() {

    }
}

and instantiate it this way:

.controller('LoginController', ['$rootScope', '$http', '$location', '$cookieStore', 'AuthService', 'AUTH_EVENTS', 'localStorageService',
    ($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService) =>
        new LoginController($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService);
])

After upgrading to AngularJS 1.3.0 this does not work at all. The "controller as" syntax is completely broken (when used in this fashion). We define a form on the page with ng-submit:

<form name="loginForm" ng-submit="loginCtl.login(dc.credentials)" novalidate>
    ... fields here
    <button type="submit">Login</button>
</form>

The loginCtl.login() does nothing, and no errors are output to the console.

After a lot of debugging and some digging, I believe the breaking change in AngularJS is this:

https://github.com/angular/angular.js/issues/8876 https://github.com/angular/angular.js/pull/8882 (added note to documentation)

If I modify my controller as such:

.controller('LoginController', ['$rootScope', '$http', '$location', '$cookieStore', 'AuthService', 'AUTH_EVENTS', 'localStorageService',
    function ($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService) {
        var loginCtrl = new LoginController($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService);

        // since controllers always return 'this', extend 'this' with the controllers
        // properties and it's prototype's properties
        _.extend(this, loginCtrl);
        _.extend(this, loginCtrl["__proto__"]);
    }
])

Then I can get it working, but this seems messy (and I'm not sure if I would have to chain up prototypes in case of superclasses).

Has anyone else run into this and have a better approach for defining these classes in TypeScript?

4
  • 2
    You could just do .controller('LoginController', ['dep'..., LoginController]); You do not have to new up, injector will do it for you. Commented Oct 23, 2014 at 17:27
  • This might help as well stackoverflow.com/questions/26109895/… Commented Oct 23, 2014 at 18:04
  • Thank you for making this more clear! Commented Oct 23, 2014 at 21:17
  • Glad i could!! You are welcome.. :) Commented Oct 23, 2014 at 22:07

2 Answers 2

2

As PSL said, this is the problem:

.controller('LoginController', ['$rootScope', '$http', '$location', '$cookieStore', 'AuthService', 'AUTH_EVENTS', 'localStorageService',
    ($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService) =>
        new LoginController($rootScope, $http, $location, $cookieStore, AuthService, AUTH_EVENTS, localStorageService);
])

You can simply use LoginController in place of the giant arrow function.

See this comment in the issue you linked about how returning an object is incorrect; the function needs to be something that works when the new operator is used on it.

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

1 Comment

Marking this as the correct answer. Thanks a lot - once I got past this issue upgrading from 1.2.26 to 1.3.0 was a breeze.
0

As PSL said but with $inject... I posed a similar question Angular 1.3 breaking changes - scope set but reset before $apply

I've put my answer here: http://plnkr.co/edit/NMPXFd67WLXHjhrfync2

//other dependencies deleted for brevity
.controller('LoginController', ['$scope', LoginController]);
LoginController.$inject = ['$scope'];

2 Comments

You don't need to return a new instance or use $inject once you use the minify-friendly notation: plnkr.co/edit/BpKeqjjNPOFs9GX4YXnA?p=preview
@GFoley83 - spot on. thanks for the feedback, I tested it minified: plnkr.co/edit/nv1mgzhgrpLi7VeVh9C2?p=preview

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.