0

This works:

Plunker controllerAs in js

input-form.html

<form name="inputForm" ng-submit="inputForm.$valid && inputCtrl.emitData()" novalidate>
  <textarea name="topic1Data" ng-model="inputCtrl.inputValues.topic1Data" rows="10" cols="30" required></textarea>
  <button type="submit" class="btn btn-info btn-lg" ng-disabled="!inputForm.$valid">Compare</button>
</form>

inputForm.js

"use strict";

(function() {
  var inputForm = angular.module('input-form', []);

  inputForm.directive('inputForm', function() {
    return {
      restrict: 'E',
      templateUrl: 'input-form.html',
      scope: {data: "="},
      controllerAs: 'inputCtrl',
      bindToController: true,
      controller: function() {
        var inputCtrl = this;
        inputCtrl.inputValues = {topic1Data: 123456789};

        inputCtrl.emitData = function() {
          inputCtrl.data =  inputCtrl.inputValues.topic1Data;
        };
      }
    };
  });
})();

Source: https://stackoverflow.com/a/29558554/2848676

This doesn't work:

Plunker controller as in html

input-form.html

<form name="inputForm" ng-controller="InputController as inputCtrl" ng-submit="inputForm.$valid && inputCtrl.emitData()" novalidate>
  <textarea name="topic1Data" ng-model="inputCtrl.inputValues.topic1Data" rows="10" cols="30" required></textarea>
  <button type="submit" class="btn btn-info btn-lg" ng-disabled="!inputForm.$valid">Compare</button>
</form>

inputForm.js

"use strict";

(function() {
  var inputForm = angular.module('input-form', []);

  inputForm.directive('inputForm', function() {
    return {
      restrict: 'E',
      templateUrl: 'input-form.html',
      scope: {data: "="},
      bindToController: true
    };
  });

  inputForm.controller('InputController', function(){
    var inputCtrl = this;
    inputCtrl.inputValues = {topic1Data: 123456789};

    inputCtrl.emitData = function() {
      inputCtrl.data =  inputCtrl.inputValues.topic1Data;
    };
  });
})();

I found an article by Pascal Precht that seemed to say the solution was bindToController but I'm using bindToController and it doesn't work still.

How come the controllerAs in the JavaScript works but not the ng-controller=...as... in HTML?

Community
  • 1
  • 1
Michael Osofsky
  • 11,429
  • 16
  • 68
  • 113
  • 1
    From what I understand **bindToController** only works with **controllerAs** - https://github.com/johnpapa/angular-styleguide#style-y076 – camden_kid Apr 10 '15 at 16:19
  • 1
    What exactly doesn't work? I tried your plunkr, and it displays 123456789 in the textarea. What do you expect to happen, and what happens instead? – JB Nizet Apr 10 '15 at 16:29
  • 1
    @JBNizet sorry I put the wrong Plunker link for the version that works. I've corrected it in the question, but here it is for your convenience: http://plnkr.co/edit/jJr649vljMyqqZx8P9Um?p=preview. Expected behavior: given a number entered in the text area, when the user presses the compare button, then the number should appear as a label. It works with `controllerAs` in JS but not with `... as ...` in HTML. – Michael Osofsky Apr 10 '15 at 16:50

1 Answers1

1

bindToController works with a controller defined on the directive definition object:

.directive("foo", function(){
  return {
    //..
    bindToController: true,
    controller: "FooCtrl",
    controllerAs: "foo"
  };
});

In other words, when $compile service runs and compiles/links the directives, it collects the directives and binds to a directive.controller object. That is the controller that "binds" to the isolate scope properties.

In your case, you assumed (incorrectly) that a controller defined in the template with ng-controller="FooCtrl as foo" would work in the same manner. There is no basis for that assumption and the article that you linked to never showed that as an option.

The template can instantiate numerous controllers, not to mention that a template could be loaded asynchronously (with templateUrl), so the bindToController was never meant to be used in such a manner.

New Dev
  • 48,427
  • 12
  • 87
  • 129
  • Thanks. I seem to be missing some knowledge. The two methods of creating controllers seemed equivalent. What resource would you suggest I read to understand the differences between `controllerAs` syntax in JavaScript and `ng-controller=…as…` syntax in HTML? – Michael Osofsky Apr 10 '15 at 21:37
  • 1
    @MichaelOsofsky, both act as an alias, in that they "publish" the controller function object on the scope under the `as alias` alias. But defining a controller on the directive definition object has other uses, like making it available via `require` or, for that matter, enabling the `bindToController` – New Dev Apr 10 '15 at 21:40
  • I wonder if AngularJS should give an error if `bindToController` is specified without `controller`. – Michael Osofsky Apr 10 '15 at 23:29
  • 1
    That error must have been introduced in a recent version because my version, AngularJS 1.3.15, does not report the error whereas your version, 1.4.0-rc.0, does. – Michael Osofsky Apr 13 '15 at 18:50
  • One more gotcha I ran into applying this solution was [AngularJS "normalization"](https://docs.angularjs.org/guide/directive). I wanted to name the attribute `topic1Name` instead of `data`. I finally figured out I had to name the attribute `topic-1-name` in HTML and `topic1Name` in JavaScript. Similar problem here: http://stackoverflow.com/questions/29612749/angularjs-link-function-not-called-due-to-attribute-name-normalization – Michael Osofsky Apr 14 '15 at 16:35