web-dev-qa-db-fra.com

Simple AngularJS Form n'est pas défini dans Scope

Je commence à jouer avec les formulaires AngularJS dans jsfiddle et j'ai déjà rencontré un problème où un exemple de formulaire très simple ne fonctionne pas comme prévu. Tout ce que j'ai est un formulaire nommé et sa portée ne s'affiche pas pour une raison quelconque (j'attends une instance de FormController).

J'ai un violon mis en place, et ci-dessous est le code de base:

[~ # ~] html [~ # ~]

<div id="mainContainer" ng-app="angularTest" ng-controller="MainCtrl">
    <h1>The Form</h1>
    <form name="theForm">
        <input name="myName" type="text" ng-model="model.name" />
        <input name="submit" type="submit" />
    </form>
</div>

[~ # ~] js [~ # ~]

var app = angular.module('angularTest', []);

app.controller('MainCtrl', ['$scope', function($scope) {
    $scope.model = { name: 'Model Name' };
    console.log($scope.theForm); //displays 'undefined'
}]);

Je ne trouve pas beaucoup d'exemples simples de cela sur jsfiddle, alors je ne savais pas s'il pouvait s'agir d'une interaction étrange avec des sites similaires (la plupart des exemples que je trouve n'utilisent pas de contrôleurs formels). J'ai aussi essayé sur Plunker de vérifier, mais je rencontre le même problème.

Je suis sûr que je manque quelque chose de très évident, mais je ne vois pas beaucoup de choses à changer ou Tweak ici. Toute aide est grandement appréciée!

58
chucknelson

Le formulaire ne s'enregistre qu'avec le $scope Du contrôleur après que le contrôleur a été exécuté initialement. Par conséquent, la console.log($scope.theForm) retournera undefined même si tout est configuré correctement.

Dans votre exemple pour réagir à la présence de theForm, vous pouvez configurer un observateur sur theForm pour définir le texte de débogage en fonction de sa présence:

$scope.$watch('theForm', function(theForm) {
    if(theForm) { 
        $scope.formDebugText = 'Form in Scope';
    }
    else {
        $scope.formDebugText = 'Form is Undefined';
    }        
});

qui peut être vu en action à http://jsfiddle.net/9k2Jk/1/

37
Michal Charemza

Un bon moyen de réaliser cela sans utiliser watch (ce qui est un peu excessif) consiste à définir un objet dans la portée dans lequel vous allez enregistrer le formulaire.

HTML

<div id="mainContainer" ng-app="angularTest" ng-controller="MainCtrl">
    <h1>The Form</h1>
    <form name="form.theForm">
        <input name="myName" type="text" ng-model="model.name" />
        <input type="button" value="Here the scope" ng-click="display()"/>
        <input name="submit" type="submit" />
    </form>
</div>

JS

var app = angular.module('angularTest', []);

app.controller('MainCtrl', ['$scope', function($scope) {
    $scope.model = { name: 'Model Name' };
    $scope.form = {};
    $scope.display = function () {
        console.log($scope.form.theForm);
    }
}]);
87
IxDay

Ce qui l’a corrigé pour moi a été d’utiliser un objet parent sur le $scope.

Dans le contrôleur:

$scope.forms = {};
$scope.registerUser = function registerUser() {
    if ($scope.forms.userForm.$valid) {
        alert('submit');
    }
};

Dans le modèle:

<form name="forms.userForm" ng-submit="registerUser()">

La raison:

Si tu utilises <form name="userForm"... au lieu de <form name="forms.userForm"... _ attache le formulaire à une portée enfant, mais comme $ scopes utilise un héritage prototype, dès que j'ai déclaré un littéral d'objet vide sur la portée $ originale, le formulaire lui a été associé.

30
hofnarwillie

Voici le moyen recommandé d'accéder à la variable de formulaire: https://docs.angularjs.org/guide/forms - Liaison à la forme et à l'état de contrôle

En HTML:

<form name="form">  
<input type="button" ng-click="reset(form)" value="Reset" />
</form>

Vous passerez le nom du formulaire sous forme de variable à la fonction.

En JS:

$scope.reset = function(form) { 
  alert(form); 
};

La variable 'formulaire' ne devrait PAS être indéfinie maintenant.

22
bogdanmatra

Dans mon cas, j'ai utilisé ng-include pour générer une sous-portée, donc dans la portée actuelle, la propriété est undefined, pour être sûr et éviter les problèmes de sous-portée, nous devrions utiliser une variable inversée pour nommer le formulaire exactement comme form.theForm.

Mais assurez-vous que vous avez déclaré ce nom de formulaire dans votre contrôleur à l’avance.

<form name="form.theForm">
    <input name="myName" type="text" ng-model="model.name" />
    <input name="submit" type="submit" />
</form>

app.controller('MainCtrl', ['$scope', function($scope) {
    $scope.model = { name: 'Model Name' };
    //You have to declare here, else it will trigger undefined error still.
    $scope.form = {
      theForm: {} 
    };

    $scope.reset = function(){
       $scope.form.theForm.$setPristine();
    }
}]);
3
Neeson.Z

Vous pouvez réinitialiser le formulaire à partir de votre contrôleur avant d'essayer d'accéder à $ scope.form avec cette ligne de code. $ scope.form sera alors disponible.

angular.element(jQuery('.form-control')).triggerHandler('input')
1
Ben Warren

J'ai écrit une directive pour traiter ce problème. C'est un attribut que vous pouvez mettre sur votre formulaire et transmettre une fonction à laquelle s'exécutera lorsque le formulaire sera prêt.

Javascript

angular.module('app').directive('formInit', function(){
  return {
    restrict: 'A',
    scope: {
      init: '&formInit'
    },
    controller: function($scope, $element){
      var name = null;
      if ($element[0] && $element[0].name){
        name = $element[0].name;
      }

      var listener = $scope.$watch('init', function(){
        if ($scope[name] && $scope.init){
          $scope.init();
          listener();
        }
      });
    }
  };
});

Exemple HTML

<form name="test" form-init="testing()">

testing est une fonction de la portée de vos contrôleurs.

0
Simon Trewhella