Warum undefined innerhalb von ng-include bilden, wenn $ pristine oder $ setDirty () geprüft werden?

Der folgende Code löst den Fehler "TypeError: Die Eigenschaft '$ pristine' von undefined kann nicht gelesen werden" aus, wenn ich auf die Schaltfläche "check" klicke.

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

Das Problem ist, dass mein Ctrl2 das productForm nicht sehen kann. Zuerst dachte ich, dass dies mit der prototypischen Vererbung zu tun hat, die ng-include macht, wenn ein untergeordneter Bereich erstellt wird. Deshalb habe ich versucht, eine Variable in Ctrl2 hinzuzufügen:

$scope.productForm = {}; 

Dies hat den Fehler beseitigt, aber mein Controller hat $ pristine oder $ dirty immer noch nicht richtig gesehen.

Ich habe es endlich geschafft, indem ich ein $ scope.formHolder-Objekt über der productForm hinzufügte:

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>

Warum funktioniert das? Und gibt es einen besseren Weg, dies zu tun?

Ich bin auf diese Weise gekommen, weil ich ein funktionierendes Formular & Controller / Template hatte, das ich woanders wiederverwenden wollte. Ich sollte wahrscheinlich eine Direktive machen, aber bis auf die $ pristine- und $ dirty-Features des Formulars funktionierte alles einwandfrei - alle ng-model-Variablen wurden korrekt übergeben.

Wie kann ich ein Formular in einem ng-include als vorrangig festlegen? hat eine Antwort, die "gegen alle Regeln verstößt", aber komplizierter erschien.

Wenn ich schreibe, wann fügt der Formular-Controller dem Bereich $ pristine hinzu und zu welchem Bereich?

Bearbeiten / Beantworten:

Meine ursprüngliche Frage lässt sich auf die Frage reduzieren, wie die Formularanweisung in den Geltungsbereich schreibt. Ich hatte den Eindruck, dass es das Ding aufnehmen würde

<form name="productForm">...

und füge Eigenschaften hinzu, wie

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

Es wird jedoch direkt auf productForm geschrieben:

$scope.productForm = formObject;

Das Formularobjekt wird also im untergeordneten Objekt und nicht im übergeordneten Objekt gespeichert, wie in der ausgewählten Antwort erläutert.

Das Schlüsselnugget bei der Vererbung von untergeordneten Bereichen, das mir geholfen hat, ist, dass die Kette beim Lesen, aber nicht beim Schreiben konsultiert wird. Wenn Sie also childScope.myThing.property = '123' setzen, muss zunächst gelesen werden, um herauszufinden, was myThing ist. Während das Setzen von childScope.myThing = '567' ein direktes Schreiben ist und keinen Blick auf die übergeordnete Kette erfordert. Dies wird alles besser erklärt in:Welche Nuancen hat die prototypische / prototypische Vererbung von Oszilloskopen in AngularJS?

Antworten auf die Frage(3)

Ihre Antwort auf die Frage