1

I can't figure out why this plnkr isn't working.

I'm trying to bind a simple function from a parent controller to a child custom directive. If I use &, it doesn't work, but if I use = or <, it works fine. I understand this is bad practice, but why does it work and & doesn't? Maybe I'm missing something very simple?

Here's the script:

JS

var app = angular.module('myApp',['ngMaterial']);

app.controller('mainCtrl',mainCtrl);
function mainCtrl(){
  var main = this;

  main.test = function(){console.log("test")};
}

app.directive('myDirective',myDirective);
function myDirective(){
  return {
    scope: {},
    controller: myCtrl,
    controllerAs: "dir",
    bindToController: {
      //fn: '&'  //This doesn't work
      fn: '<' // This works
    },
    template: '<md-button ng-click="dir.fn()" class="md-raised">click</md-button>'
  };

  function myCtrl(){

  }
}

HTML

  <div ng-app="myApp" ng-controller="mainCtrl as main">
    <my-directive fn="main.test"></my-directive>
  </div>
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
Charlie Patton
  • 435
  • 2
  • 12

1 Answers1

1

& binding provides a wrapper function to execute an expression. So all that dir.fn() does is getting test property.

The documentation says,

& or &attr - provides a way to execute an expression in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name.

To make it work as expected it should be

<my-directive fn="main.test()"></my-directive>
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • The key here was that the attribute binding in the html needs the parentheses. I'm not exactly clear on why that is; I'm sure it's a subtlety of Angular that I'm missing. In pure JS, I think of `myFunction()` as executing a function, and `myFunction` as a function reference. Can you explain? – Charlie Patton Apr 19 '17 at 14:39
  • 1
    That's the correct way to think of it. The thing that matters is the context. `main.test()` expression is passed unevaluated to & binding and is evaluated each time when `dir.fn()` is called. If functions were allowed in Angular expressions, the same thing could be done with `fn="function () { return main.test() }"` for `<` binding. – Estus Flask Apr 19 '17 at 14:53
  • I misquoted the documentation and updated the quote for & binding. – Estus Flask Apr 19 '17 at 14:53