Philip E
Philip E

Reputation: 858

How do you access a method in a Controller from a Directive

In this directive i want to be able to show the Month of Birth for each user in the Array on ng-repeat. How can i access the getBirthMonth(DOB) method in the Controller from the Directive? Each user's DOB is passed as an argument to the method during each iteration

i.e

<p  ng-repeat="x in customerInfo">
  Name: {{x.name}} Address: {{x.address}}
  <span ng-init="birthMonth = getBirthMonth(DOB)"> {{birthMonth}}</span>
</p>

Here is a Plunkr: https://plnkr.co/edit/6TBqsjDllTCUAPQc9BzL?p=preview

Desired Result: Name: John Address: 22 Infinite loop Birth Month: February

Upvotes: 0

Views: 62

Answers (3)

Ron Brogan
Ron Brogan

Reputation: 901

To answer your question as appropriately as possible, I've forked your provided plunker and made it work as expected.

https://plnkr.co/edit/hN0AYYxLGxpl7e2sWhSw?p=preview

Some things to note: You can pass in your data and functions to the directive. I've used the bindToController on the directive in order to use modern practices for bindings in the DOM. (See https://github.com/angular/angular.js/wiki/Understanding-Scopes for more info about scopes)

The updated directive definition is:

  restrict: 'E',
  scope:{},
  bindToController: {
    customerInfo: '=info',
    calcDob: "&"
  },
  templateUrl: 'my-customer-plus-vojta.html',
  controller: function(){

  },
  controllerAs: "$ctrl"

And the use of the directive is:

<my-customer info="names" calc-dob="getBirthMonth"></my-customer>

I also changed the directive template a bit, using the new controllerAs value, and removed the ngInit

Name: {{x.name}} Address: {{x.address}}: {{$ctrl.calcDob()(x.DOB)}}

Upvotes: 0

Petar Krivoshiev
Petar Krivoshiev

Reputation: 150

What you are trying to do is an antipattern. Try to encapsulate the specific functionality in a service. This way you can reuse it through the application:

angular.module('docsIsolationExample', [])
  .service('getBirthMonth', [function() {

return function (DOB) {
  var month = [];
  month[0] = "January";
  month[1] = "February";
  month[2] = "March";
  month[3] = "April";
  month[4] = "May";
  month[5] = "June";
  month[6] = "July";
  month[7] = "August";
  month[8] = "September";
  month[9] = "October";
  month[10] = "November";
  month[11] = "December";

  var d = new Date(DOB),
  n = month[d.getMonth()];

  return n; // returns monthName i.e February
}

}])

A working example: https://plnkr.co/edit/RlSvfNo5qgjblHImYbnc

You don't need to use the ng-init, only use the function instead:

<span>{{getBirthMonth(x.DOB)}}</span>

Try the Angular 1 Style Guide by johnpapa: https://github.com/johnpapa/angular-styleguide/tree/master/a1 - it produces much better readable code.

Upvotes: 0

Callum Linington
Callum Linington

Reputation: 14417

You just create a service for it to sit in ( plnkr ) :

.service('birthMonth', function () {
  this.getBirthMonth = function (DOB) {
      var month = [];
      month[0] = "January";
      month[1] = "February";
      month[2] = "March";
      month[3] = "April";
      month[4] = "May";
      month[5] = "June";
      month[6] = "July";
      month[7] = "August";
      month[8] = "September";
      month[9] = "October";
      month[10] = "November";
      month[11] = "December";

      var d = new Date(DOB),
      n = month[d.getMonth()];

      return n; // returns monthName i.e February
  }
});

Directive:

.directive('myCustomer', ['birthMonth', function(birthMonth) {
  return {
    restrict: 'E',
    scope: {
      customerInfo: '=info'
    },
    templateUrl: 'my-customer-plus-vojta.html',
    link: function (scope) {
      scope.getBirthMonth = birthMonth.getBirthMonth;
    }
  };
}])

HTML:

<p  ng-repeat="x in customerInfo">
  Name: {{x.name}} Address: {{x.address}}
  <span> {{getBirthMonth(x.DOB)}}</span>
</p>

Upvotes: 3

Related Questions