user348173 user348173 - 3 months ago 14
AngularJS Question

How to avoid bind(this) in Angular directive controllers

I have ES6 class for directive controller:

export default class LoginController {
constructor($state, store, auth, principal) {
this.$state = $state;
this.store = store;
this.auth = auth;
this.principal = principal;
this.loginFailed = false;
this.loginErrorMessage = '';
}

onLoginSuccess(profile, token) {
this.store.set('profile', profile);
this.store.set('token', token);
this.principal.updateCurrent(profile, token);

this.$state.go('main');
}

onLoginFailed(error) {
this.loading = false;
this.loginFailed = true;
this.loginErrorMessage = error.details.error_description;
}


signGoogle() {
this.signOAuth('google-oauth2');
}

signOAuth(connection) {
this.loading = true;
this.auth.signin({
popup: true,
connection: connection,
scope: 'openid name email'
}, this.onLoginSuccess.bind(this), this.onLoginFailed.bind(this));
}
}

LoginController.$inject = [
'$state', 'localStorageService', 'auth', 'principal'
];


In the
signOAuth
method I have two callbacks:
onLoginSuccess
and
onLoginFailed
. To properly call them I have to use
bind(this)
otherwise I get
undefined
for
this
in calbacks.

Is it possible to avoid
bind
? Or, it's a normal approach to work with ES6 and angular 1?

Answer

You can move the binding to the constructor, if that helps (not really):

constructor($state, store, auth, principal) {
    this.$state = $state;
    this.store = store;
    this.auth = auth;
    this.principal = principal;
    this.loginFailed = false;
    this.loginErrorMessage = '';      
    this.onLoginSuccess = this.onLoginSuccess.bind(this);
    this.onLoginFailed  = this.onLoginFailed.bind(this);
}

..., add a level of indirection:

this.auth.signin({
    popup: true,
    connection: connection,
    scope: 'openid name email'
  },
  (profile, token) => this.onLoginSuccess(profile, token),
  (error)          => this.onLoginFailed(error)
)

..., or create class instance fields (which may require you to add additional plugins to your transpiler, as they aren't part of ES2015 AFAIK; for Babel, I think that transform-class-properties handles these):

onLoginSuccess = (profile, token) => {
    this.store.set('profile', profile);
    this.store.set('token', token);
    this.principal.updateCurrent(profile, token);

    this.$state.go('main');
}

onLoginFailed = error => {
    this.loading = false;
    this.loginFailed = true;
    this.loginErrorMessage = error.details.error_description;
}   
Comments