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

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.