52 votes

L'objet de formulaire de dialogue modal AngularJS n'est pas défini dans le contrôleur

Nous avons une page qui s'ouvre une boîte de dialogue modale avec une forme comme ci-dessous. Cependant, quand nous avons touché le contrôleur doit gérer l'action du formulaire, la forme de l'objet n'est pas définie et que je suis trop Angulaire débutant de comprendre pourquoi...

Ceci est la page parent contrôleur de titulaire de la fonction pour ouvrir la boîte de dialogue modale:

app.controller('organisationStructureController', ['$scope', ..., '$modal', function ($scope, ..., $modal) {

    $scope.openInvitationDialog = function (targetOrganisationId) {
      $modal.open({
          templateUrl: 'send-invitation.html',
          controller: 'sendInvitationController',
          resolve: {$targetOrganisationId: function () {
            return targetOrganisationId;
          }
          }
        }
      );
    };

sur une page comme ceci:

// inside a loop over organisations
<a ng-click="openInvitationDialog({{organisation.id}})">Invite new member</a>

l'invitation-dialogue html ressemble à ceci:

    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <!-- ... -->
            </div>
            <div class="modal-body">
                <form name="invitationForm">

                    <div class="form-group">
                        <label for="email" style="color:white;">Email</label>
                        <input type="email" class="form-control"  autocomplete="off" placeholder="New member email" id="email" name="email" ng-model="invitation.email" required="true"/>
                        <span class="error animated fadeIn" ng-show="invitationForm.email.$dirty && invitationForm.email.$error.required">Please enter an email address!</span>
                        <span class="error animated fadeIn" ng-show="invitationForm.email.$error.email">Invalid email</span>
                    </div>

                    <!-- ... -->

                    <div class="modal-footer">
                        <button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button>
                        <button type="submit" class="btn btn-primary" ng-click="sendInvitation()">Invite</button>
                    </div>
                </form>
            </div>
        </div>
    </div>

Le contrôleur doit gérer l'invitation est ailleurs:

  app.controller('sendInvitationController', ['$targetOrganisationId', '$scope', ...,
    function ($targetOrganisationId, $scope, ...) {

    $scope.invitation = {
      // ...
      targetOrganisation: {
        id: $targetOrganisationId
      }
    };

    $scope.sendInvitation = function () {

      // $scope.invitationForm is undefined
      if ($scope.invitationForm.$invalid) {
        return false;
      }

      // send the invitation...

    };
  }]);

Quelle est donc la bonne façon d'obtenir la forme de la portée dans le contrôleur?

Peut-être que j'ai besoin d'injecter $modal dans la sendInvitationController et ajouter l' sendInvitation fonction de celle-ci? Mais quand je le fais, que l'action ne pénètre jamais dans le contrôleur. Ou dois-je ajouter une fonction qui gère l'action soumettre à l' $modal.open({ ... au lieu de référencer le contrôleur? Bien que je préfèrerais avoir le sendInvitationController dans son propre fichier et la portée.

Merci pour toute aide!

MODIFIER

Nous avons trouvé plusieurs choses qui nous a aidés à construire une solution de contournement et pourraient aider quelqu'un à une réponse à la question elle-même:

  1. l' $scope.invitation objet n'est pas définie dans l' sendInvitationController mais qui détient les données correctes, tandis que d' $scope.invitationForm reste indéfini.
  2. à l'intérieur de la send-invitation.html nous pouvons accéder $scope.invitationForm.$invalid et de procéder à la validation de droite il y a: <button type="button" ng-click="sendInvitation()" ng-disabled="invitationForm.$invalid">Invite</button>

La question est donc: pourquoi la liaison de l' invitationForm objet à l' $scope échouer sur soumettre, tandis que le modèle de formulaire de lie correcetly?

78voto

Robin Points 616

J'avais le même problème et je pouvais le résoudre en définissant l'objet de formulaire dans l'étendue du contrôleur de modaux. Pour que votre code fonctionne, insérez par exemple $scope.form = {}; au début de votre contrôleur et modifiez votre balise de formulaire en <form name="form.invitation"> . Ensuite, $scope.form.invitation.$invalid doivent être remplis.

39voto

gertas Points 7113

Pour placer invitationForm directement dans la portée de votre contrôleur parent, vous devez contourner la portée transcluse de cette façon:

 <form name="$parent.invitationForm">
 

Ci-dessus créera automatiquement un objet formulaire dans votre contrôleur parent. Pas besoin de trucs de pré-initialisation, de longs chemins d'objet ou de passage par événement. Il suffit d’y accéder avec $scope.invitationForm une fois le modal ouvert.

19voto

squid314 Points 1155

La réponse à la question du "Pourquoi?" est "portée". tl;dr vous avez créé une nouvelle ampleur avec la boîte de dialogue modale qui cachait la portée de l'objet de formulaire à partir de votre contrôleur.

Si nous simplifier votre code, nous reçois à peu près le suivant:

<div ng-ctrl="organizeCtrl">
  <modal-dialog>
    <form name="invitationForm">
      <input type="email" ng-model="invitation.email" placeholder="Enter email..." />
      <input type="submit" ng-click="sendInvitation()" text="Invite!" />
      <input type="button" ng-click="cancel()" text="Cancel  :(" />
    </form>
  </modal-dialog>
</div>

(C'est une version très simplifiée qui doit toujours avoir tous les composants de base.) Maintenant, regardons où les étendues sont créés et ce qui est injecté dans les.

<div ng-ctrl="sendInvitationController">
<!-- scope created above with "invitation" and "sendInvitation" from sendInvitationController -->
  <modal-dialog>
  <!-- scope created above for the modal dialog transclude -->
    <form name="invitationForm">
    <!-- add "invitationForm" to the modal dialog's scope -->
      <input type="email" ng-model="invitation.email" placeholder="Enter email..." />
      <input type="submit" ng-click="sendInvitation()" text="Invite!" />
      <input type="button" ng-click="cancel()" text="Cancel  :(" />
    </form>
  </modal-dialog>
</div>

Ici, vous pouvez voir qu'il y a un nouvel enfant à la portée, à l' <modal-dialog> élément et qui est l'endroit où l' invitationForm objet est effectivement ajouté. C'est pourquoi vous ne pouvez pas voir l'objet dans l' sendInvitationController mais vous pouvez le voir sur les boutons pour ng-disabled. Si vous voulez être en mesure d'accéder au formulaire de construire à l'extérieur de l' <modal-dialog> élément (par exemple, dans l' sendInvitationController) vous aurez besoin de passer que dans l'appel de la fonction:

<div ng-ctrl="organizeCtrl">
  <modal-dialog>
    <form name="invitationForm">
      <input type="email" ng-model="invitation.email" placeholder="Enter email..." />
      <input type="submit" ng-click="sendInvitation(invitationForm)" text="Invite!" />
      <input type="button" ng-click="cancel()" text="Cancel  :(" />
    </form>
  </modal-dialog>
</div>

Avec le contrôleur d'accepter l'invitation de formulaire en tant que paramètre à l' sendInvitation fonction de:

app.controller('sendInvitationController', ['$targetOrganisationId', '$scope', ...,
  function ($targetOrganisationId, $scope, ...) {
  $scope.invitation = {
    targetOrganisation: {
      id: $targetOrganisationId
    }
  };
  $scope.sendInvitation = function (form) {
    if (form.$invalid) {
      return false;
    }
    // send the invitation...
  };
}]);

@Robin identifié l'autre solution, plus précisément à créer un objet ancré dans le champ d'application de l' sendInvitationController , puis joignez le formulaire directement à cet objet, en s'appuyant sur Angulaire du champ d'application de la traversée mécanisme de trouver l' form objet sur la portée à l'extérieur de l' <modal-dialog> et de fixer la forme de l'objet pour que. Notez que si vous n'avez pas spécifié $scope.form = {} dans la sendInvitationController, Angulaire aurait créé un nouvel objet pour l' form sur le périmètre de l' <modal-dialog> et vous n'auriez toujours pas été en mesure d'y accéder dans l' sendInvitationController.

J'espère que cela vous aide à vous ou à d'autres personnes d'apprentissage sur Angulaire de portée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X