Почему форма не определена внутри ng-include при проверке $ pristine или $ setDirty ()?

Следующий код выдает ошибку «Ошибка типа: невозможно прочитать свойство« $ pristine »неопределенного», когда я нажимаю кнопку «Проверить».

app.controller('MainCtrl', function($scope) {
  // other stuff
})

.controller('Ctrl2', function($scope) {
  $scope.product = {description:'pump'};
  $scope.output = 'unknown';
  // uncomment to avoid undefined error, still can't see $pristine
  // $scope.formHolder = {};
  $scope.checkForm = function() {
    $scope.descriptionTest = $scope.product.description;
    if ($scope.formHolder.productForm.$pristine) {
      $scope.output = 'yes';
    }
    if ($scope.formHolder.productForm.$dirty) {
      $scope.output = 'no' 
    }
  }
});

HTML

  <body ng-controller="MainCtrl">
    <div >
      <ng-include ng-controller="Ctrl2" src="'myForm.html'"></ng-include>
    </div>
  </body>

myForm.html

<form name="productForm" novalidate>
  <h2>myForm</h2>
  description: <input type="text" name="description" ng-model="product.description"/>
  <br>
  <button ng-click="checkForm()">Check Form</button>
  <br>
  Form Pristine: {{output}}
  <br><br>
  I can see the description: {{descriptionTest}}
</form>

plunkr

Проблема в том, что мой Ctrl2 не видит productForm. Сначала я подумал, что это связано с прототипным наследованием, которое делает ng-include при создании дочерней области, поэтому я попытался добавить переменную в Ctrl2:

$scope.productForm = {}; 

Это избавило от ошибки, но мой контроллер все еще не правильно видел $ нетронутый или $ грязный.

Наконец-то я заработал, добавив объект $ scope.formHolder над productForm:

plunkr

.controller('Ctrl2', function($scope) {
  $scope.product = {description:'pump'};
  $scope.output = 'unknown';
  // uncomment to avoid undefined error, still can't see $pristine
  $scope.formHolder = {};
  $scope.checkForm = function() {
    $scope.descriptionTest = $scope.product.description;
    if ($scope.formHolder.productForm.$pristine) {
      $scope.output = 'yes';
    }
    if ($scope.formHolder.productForm.$dirty) {
      $scope.output = 'no' 
    }
  }
});

HTML

<form name="formHolder.productForm" novalidate>

Почему это работает? И есть ли лучший способ сделать это?

Я закончил таким образом, потому что у меня была рабочая форма и контроллер / шаблон, который я хотел использовать где-то еще. Вероятно, мне следовало бы сделать директиву, но все работало нормально, кроме $ pristine и $ dirty функций формы - все переменные ng-модели были переданы правильно.

Как я могу установить форму, содержащуюся в ng-include, чтобы быть prestine? есть ответ, который «нарушает все правила», но кажется более сложным.

Когда я пишу, когда контроллер формы добавляет $ pristine в область действия и в какую область?

Редактировать / Ответить:

Мой первоначальный вопрос может быть сведен к путанице относительно того, как директива формы записывает в область видимости. У меня было впечатление, что это займет

<form name="productForm">...

и добавить свойства к нему, как

$scope.productForm.$pristine = function() {...}

однако, он пишет прямо поверх productForm:

$scope.productForm = formObject;

Таким образом, объект формы хранится в дочернем, а не родительском объекте, как объяснено в выбранном ответе.

Ключевой самородок в наследовании дочернего контекста, который мне помог, заключается в том, что с цепочкой обращаются при чтении, а не при записи. Поэтому, если вы установите что-то вроде childScope.myThing.property = '123', тогда как это выглядит как запись, сначала нужно выполнить чтение, чтобы узнать, что такое myThing. Принимая во внимание, что установка childScope.myThing = '567' является прямой записью и вообще не предполагает просмотра родительской цепочки. Это все лучше объясняется в:Каковы нюансы объема прототипного / прототипического наследования в AngularJS?

Ответы на вопрос(3)

Ваш ответ на вопрос