Why does `controllerAs` in JavaScript work but not

2019-09-03 02:06发布

问题:

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?

回答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.