working not ejemplo div cargar angularjs angularjs-ng-include

angularjs - not - ¿Por qué formar undefined dentro de ng-include al verificar $ pristine o $ setDirty()?



ng-include angularjs (3)

Para comprender por qué la solución con formHolder funciona, formHolder debe comprender la cadena de prototipos de JavaScript . Ilustremos el primer caso sin formHolder en el siguiente pseudo código:

$parentScope = { //I''m a parent scope inside Ctrl2 productForm:{} //to avoid undefined reference error } $childScope = { //I''m a child scope created by by ng-include __protototype__: $parentScope }

Cuando se analiza la directiva de form se crea FormController que se establece en la propiedad $scope bajo la clave indicada en el valor del atributo de name . Esto es bastante equivalente a:

$childScope.productForm = $formCtrl;

Después de lo cual los 2 ámbitos se ven así:

$parentScope = { //I''m a parent scope inside Ctrl2 productForm:{} //to avoid undefined reference error } $childScope = { //I''m a child scope created by by ng-include productForm: $formCtrl __protototype__: $parentScope }

Así que en realidad terminaste con 2 propiedades en diferentes ámbitos con diferentes objetos. Ahora en el segundo caso tienes la siguiente situación:

$parentScope = { //I''m a parent scope inside Ctrl2 formHolder:{} //to avoid undefined reference error } $childScope = { //I''m a child scope created by by ng-include __protototype__: $parentScope }

Cuando la directiva de form está configurando la instancia de FormController en el $scope esta vez usa una cadena de propiedades diferente:

$childScope.formHolder.productForm = $formCtrl;

Lo que equivale a escribir:

var formHolder = $childScope.formHolder; //since formHolder isn''t defined on $childScope //the JS runtime will look for it in the prototypes chain and find it inside $parentScope //so here formHolder is the very same object you created and set on $parentScope formHolder.productForm = $formCtrl;

Espero que ayude a entender por qué funciona la segunda opción. En cuanto a la segunda parte de su pregunta, su solución es simple y perfectamente viable, pero hay un par de otras formas de manejarlo, la mejor es la que depende del contexto de uso real:

  • Uso de directivas sin ámbito de aplicación para extraer marcas comunes y partes de funcionalidad.
  • utilizando una directiva con ámbito secundario que comunique los cambios de estado a través del acceso directo a la propiedad del ámbito principal o mediante eventos emitidos
  • utilizando una directiva de inclusión personalizada que no cree un ámbito secundario

El siguiente código lanza el error "Error de tipo: no se puede leer la propiedad ''$ pristine'' de indefinido" cuando hago clic en el botón "verificar"

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

El problema es que mi Ctrl2 no puede ver el productForm. Al principio pensé que esto tenía que ver con la herencia prototípica que hace ng-include cuando tiene un alcance secundario, así que intenté agregar una variable en Ctrl2:

$scope.productForm = {};

Esto eliminó el error, pero mi controlador aún no veía correctamente $ pristine o $ dirty.

Finalmente lo puse en funcionamiento agregando un objeto $ scope.formHolder encima del 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>

¿Por qué funciona esto? ¿Y hay una mejor manera de hacer esto?

Terminé de esta manera porque tenía un formulario y un controlador / plantilla en funcionamiento que quería reutilizar en otro lugar. Probablemente debería hacer una directiva, pero todo funcionó bien, excepto las características $ pristine y $ dirty del formulario; todas las variables ng-model se pasaron correctamente.

¿Cómo puedo configurar un formulario contenido dentro de un ng-include para ser prestine? Tiene una respuesta que "rompe todas las reglas" pero parece más complicada.

¿Cuándo escribo cuándo el controlador de forma agrega $ pristine al alcance y a qué alcance?

Editar / Responder:

Mi pregunta original puede reducirse a confusión acerca de cómo la directiva de formulario escribe en el alcance. Tuve la impresión de que tomaría la cosa en

<form name="productForm">...

y añadirle propiedades, como

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

sin embargo, escribe directamente sobre productForm:

$scope.productForm = formObject;

Por lo tanto, el objeto de formulario se almacena en el Niño y no en el padre como se explica en la respuesta seleccionada.

El nugget clave en la herencia de ámbito infantil que me ayudó es que la cadena se consulta en lectura, pero no en escritura. Entonces, si establece algo como childScope.myThing.property = ''123'', aunque parece una escritura, primero tiene que hacer una lectura para averiguar qué es myThing. Considerando que establecer childScope.myThing = ''567'' es una escritura directa, y no implica mirar la cadena principal en absoluto. Todo esto se explica mejor en: ¿Cuáles son los matices del alcance prototípico / herencia prototípica en AngularJS?


Sé que esta es una pregunta antigua, pero tuve un problema similar, y cambié el html e incluí mi controlador ng dentro del archivo html.

Así que en lugar de

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

Cambiarlo también

<ng-include="''myForm.html''"></ng-include>

Y luego, en el archivo myForm.html, envuelva el código en un div, y agregue el atributo ng-controller, de modo que su myForm.html se convierta en

<div ng-controller="Ctrl2"> <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> </div>

Ahora su controlador hijo está dentro del alcance ng-include


Simplemente defina la variable (objeto vacío) en el controlador y úsela mientras define su formulario. Dado que JS angular usa prototipos de alcance debajo del capó, cuando la forma intentará acceder al alcance interno (para arrancar la variable), primero pasará por la cadena del alcance e intentará encontrar la misma variable en el alcance de la matriz.

<!—- The vars should live in the controller. I placed them here for the example. -—> <div ng-controller=“controllerName” ng-init="form={}; model={}" > <div ng-include=“ ‘path-to-the-template’ ”></div> </div> <!—- Inside path-to-the-template -—> <form name="form.createUser"> <input name="name" ng-model="model.name" /> <input name="email" ng-model="model.email" /> </form>

Enlace de referencia http://blog.152.org/2014/07/angular-form-element-not-attaching-to.html