angularjs - route - ¿Cómo puedo configurar un formulario contenido dentro de un ng-include para ser prestine?
ng-content angular 6 (4)
Bueno, una forma de hacerlo es emitir un evento, así:
angular.module(''myApp'',[])
.controller(''AdminCtrl'',function($scope){
$scope.modalReset = function(){
$scope.$broadcast(''modal-reset'');
};
})
.controller(''ModalCtrl'', function($scope){
$scope.$on(''modal-reset'', function(){
$scope.itemForm.$setPristine();
});
});
De esta manera no tienes que atravesar el dom.
Tengo el siguiente código:
<div modal="modal.shouldBeOpen" close="close()" options="opts">
<div class="modal-body">
<form novalidate name="itemForm" style="margin-bottom: 0px;">
Que está contenido dentro del archivo modal.html incluido
<div data-ng-controller="AdminController">
<ng-include src="''/Content/app/admin/partials/grid-subject.html''"></ng-include >
<ng-include src="''/Content/app/admin/partials/modal.html''"></ng-include>
</div>
En mi controlador AdminController estoy tratando de usar el siguiente código para restablecer el formulario a pristine:
$scope.itemForm.$setPristine();
Cuando hago esto, me dice que "itemForm" no está definido.
¿Hay alguna manera de que pueda establecer el contenido del formulario en forma prístina? Supongo que este es un problema de alcance, pero no estoy seguro de cómo solucionarlo. Probé la única solución de eliminar la segunda inclusión y pegar el código directamente. Esta solución funciona.
Sin embargo, queremos poder reutilizar el código, así que me gustaría poder hacer esto con una inclusión para modal.html
Tenga en cuenta que la razón por la que nos gustaría hacer esto es porque tenemos algo como lo siguiente en nuestro modal.html:
<button
class="btn float-right"
data-ng-disabled="itemForm.$pristine"
data-ng-click="modalReset()"
data-ng-show="modal.resetButton">
Reset</button>
</form>
Así que realmente estamos dentro del itemForm y nos gustaría establecerlo en $ pristine desde el botón interior.
Esta respuesta romperá todas las reglas (es decir, el cruce de DOM dentro de un controlador), pero aquí está de todos modos ...
.controller(''AdminController'', [''$scope'',''$element'',
function($scope, $element) {
$scope.$on(''$includeContentLoaded'', function() {
var childFormController = $element.find(''form'').eq(0).controller(''form'');
console.log(childFormController);
childFormController.$setPristine();
});
}]);
Esperamos a que se cargue el contenido incluido en ng, luego desde el $element
donde se define AdminController, buscamos los elementos del form
, seleccionamos el primero y luego obtenemos su FormController.
Si solo llama a $setPristine()
como resultado de alguna interacción del usuario, no tendrá que buscar el evento $includedContentLoaded
. Solo tuve que hacerlo porque no quería crear ningún componente de la interfaz de usuario para activar el operación, y cuando el controlador se ejecuta por primera vez, el formulario no existe todavía.
Vea también AngularJS: acceda a formController de un formulario colocado dentro de la directiva transcluida del controlador principal que trata el problema similar de tratar de acceder a un hijo desde un padre.
Una solución más limpia: defina una directiva (úsela en el elemento ng-include) y pásele una función AdminController como atributo. En la función de enlace de la directiva, llame a ese método y pase el FormController como parámetro. Luego, el AdminController tendrá una referencia al FormController deseado. (No me molesté en codificar esto, ya que no estoy seguro de que quiera una solución en la que tenga que usar una directiva junto con ng-include).
No rompa las reglas :) 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á a través de la cadena de 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
Si quiere lograr esto como resultado de alguna interacción del usuario, en mi opinión, una forma mucho más limpia y "angular" de hacerlo sería usar una directiva personalizada que establecerá el formulario como prístino (es decir, cuando el usuario quiera hacerlo). borre el formulario presionando esc o haciendo clic en un botón o lo que sea).
app.directive("formCleaner",
function () {
return {
restrict: ''E'',
require: ''^form'',
scope: {
callback: ''&'',
defaultText:''@''
},
template: ''<button type="button" ng-click="setFormToPristine()" class="btn btn-warning" >{{defaultText}}</button>'',
link: function (scope, element, attrs, formCtrl) {
scope.setFormToPristine = function () {
formCtrl.$setPristine();
scope.callback();
};
}
};
});
y simplemente conéctelo a algún botón en su formulario:
<form name="testForm">
<input type="text" ng-model="someModel" />
<hr/>
<input type="button" value="submit form" class="btn btn-primary" ng-disabled="testForm.$pristine"
ng-click=submitForm(testForm) />
<form-cleaner callback="resetFormCallback(testForm)" default-text="Clear Form"></form-cleaner>
</form>
Y si está buscando configurar el formulario para que se extienda directamente desde el controlador, (no como resultado de alguna interacción del usuario) como la respuesta exitosa de un POST, entonces una forma sería asignar una devolución de llamada a la directiva que será responsable de borrar el formulario y luego invocar esa devolución de llamada desde el controlador. En su opinión:
<form-cleaner callback="resetFormCallback(testForm)" default-text="Clear Form"></form-cleaner>
y el controlador:
$scope.resetFormOnSubmitCallback=function(cb){
$log.warn("simulating $http POST call.....");
$timeout(function() {
cb();
$scope.someModel=null;
}, 3000)
}
y la directiva:
return {
restrict: ''E'',
require: ''^form'',
scope: {
callback: ''&'',
defaultText:''@'',
ngDisabled:''=''
},
template: ''<button type="button" ng-disabled="ngDisabled" ng-click="submitForm()" class="btn btn-primary" >{{defaultText}}</button>'',
link: function (scope, element, attrs, formCtrl) {
var setFormToPristine=function(){
$log.log("setting form to prsitine....");
formCtrl.$setPristine();
};
scope.submitForm = function () {
scope.callback({
onFormSubmittedCallback:setFormToPristine
});
};
}
};
Ver plunk