1

I have a session service like follows with two methods representing two ways of authenticating:

angular
  .module('myApp')
  .service('sessionService', SessionService);

function SessionService() {
  var $ctrl = this;

  this.logInTypeA = function(username, password, authenticator) {
    ...
  }

  this.logInTypeB = function(username, password, authenticator) {
    ...
  }

  ...
}

I have a log in form component. I would like to have two instances of the form which use the two different log in methods but are otherwise the same:

<log-in-form log-in-method="$ctrl.sessionSerive.logInTypeA"></log-in-form>
<log-in-form log-in-method="$ctrl.sessionSerive.logInTypeB"></log-in-form>

The component's JS looks something like this:

angular
  .module('myApp')
  .component('logInForm', {
    templateUrl: 'app/components/log-in-form.template.html',
    controller: LogInFormController,
    bindings: {
      logInMethod: '&'
    }
  });

function LogInFormController() {
  var $ctrl = this;

  this.username = '';
  this.password = '';
  this.authenticator = '';

  this.logIn = function() {
    $ctrl.logInMethod($ctrl.username, $ctrl.password, $ctrl.authenticator);
  };

  ...
}

However, I get an error when I try to run this:

TypeError: Cannot use 'in' operator to search for '$ctrl' in [email protected]

How do I pass a method in a service to a component?

Thanks in advance.

2 Answers 2

5

Your HTML has a typo in the name of the service. Here is how I do this in Angular 1.4.x.

In the HTML, you should add the parameters of the function being called:

<log-in-form log-in-method="$ctrl.sessionService.logInTypeA(username, password, authenticator)"></log-in-form>
<log-in-form log-in-method="$ctrl.sessionService.logInTypeB(username, password, authenticator)"></log-in-form>

For the component, you need to add curly braces around the parameters and add each parameter name:

angular
  .module('myApp')
  .component('logInForm', {
    templateUrl: 'app/components/log-in-form.template.html',
    controller: LogInFormController,
    bindings: {
      logInMethod: '&'
    }
  });

function LogInFormController() {
  var $ctrl = this;

  this.username = '';
  this.password = '';
  this.authenticator = '';

  this.logIn = function() {
    $ctrl.logInMethod({username: $ctrl.username,
                       password: $ctrl.password,
                       authenticator: $ctrl.authenticator});
  };
  ...
}
Sign up to request clarification or add additional context in comments.

2 Comments

Oh wow. I'm facepalming at my typo. But that wasn't my only mistake! Thank you so much for explaining the bit about the parameters in the brackets, too. Great, clear answer.
@carmenism No worries, my pleasure!
0

If you want the code to use service functions by name:

<log-in-form log-in-method="logInTypeA"></log-in-form>
<log-in-form log-in-method="logInTypeB"></log-in-form>

Use attribute @ binding, and inject the service in the component:

app.component('logInForm', {
    templateUrl: 'app/components/log-in-form.template.html',
    controller: LogInFormController,
    bindings: {
      logInMethod: '@'
    }
});

function LogInFormController(sessionService) {
  var $ctrl = this;

  this.username = '';
  this.password = '';
  this.authenticator = '';

  this.logIn = function() {
    var method = sessionService[$ctrl.logInMethod];
    method($ctrl.username, $ctrl.password, $ctrl.authenticator);
  };

  ...
}

Use property accessor bracket notation to select the desired service method by name.

Comments

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.