AngularJS: désactivation de tous les contrôles de formulaire entre la soumission et la réponse du serveur

122

J'ai un dilemme sur la meilleure approche (et la bonne) si je veux désactiver les contrôles de formulaire (ou au moins les rendre indisponibles pour l'interaction de l'utilisateur) pendant une période pendant laquelle l'utilisateur clique sur le bouton "Enregistrer" ou "Soumettre" et les données voyageant sur le fil. Je ne veux pas utiliser JQuery (ce qui est mal !!!) et interroger tous les éléments sous forme de tableau (par classe ou marqueur d'attribut) Les idées que j'avais jusqu'à présent sont:

  • Marquez tous les éléments avec cm-form-controlune directive personnalisée qui s'abonnera à 2 notifications: "données envoyées" et "données traitées". Ensuite, le code personnalisé est chargé d'envoyer une deuxième notification ou de résoudre une promesse.
  • Utilisez promiseTrackercela (malheureusement!) Pour produire du code extrêmement stupide comme ng-show="loadingTracker.active()". Évidemment, tous les éléments n'ont pas ng-disabledet je ne veux pas que l'utilisateur ng-hide/showévite les boutons de "danse".
  • Mordez une balle et utilisez toujours JQuery

Quelqu'un a-t-il une meilleure idée? Merci d'avance!

MISE À JOUR: L'idée de fieldset fonctionne. Voici un simple violon pour ceux qui veulent toujours faire de même http://jsfiddle.net/YoMan78/pnQFQ/13/

HTML:

<div ng-app="myApp">
    <ng-form ng-controller="myCtrl">
        Saving: {{isSaving}}
        <fieldset ng-disabled="isSaving">
            <input type="text" ng-model="btnVal"/>
            <input type="button" ng-model="btnVal" value="{{btnVal}}"/>
            <button ng-click="save()">Save Me Maybe</button>
        </fieldset>
    </ng-form>
</div>

et JS:

var angModule = angular.module("myApp", []);

angModule.controller("myCtrl", function ($scope, $filter, $window, $timeout) {
    $scope.isSaving = undefined;
    $scope.btnVal = 'Yes';
    $scope.save = function()
    {
        $scope.isSaving = true;
        $timeout( function()
             {
                 $scope.isSaving = false;
                 alert( 'done');
             }, 10000);
    };
});
YoMan78
la source
quel service utilisez-vous pour envoyer les données à partir du formulaire? $ http ou $ resource?
François Romain
C'est en fait $ http car je n'ai pas besoin de gérer quoi que ce soit d'exceptionnel.
YoMan78
Les jeux de champs désactivés ne fonctionnent pas dans IE, ce n'est donc pas une solution. J'utilise un modal Bootstrap et je règle la toile de fond sur statique.
im1dermike
Notez qu'au moment de la rédaction de cet article, il y a un bogue qui fieldsetne peut pas être utilisé comme conteneur flexbox
George Mauer

Réponses:

283

Enveloppez tous vos champs dans fieldset et utilisez la directive ngDisabled comme ceci:

<fieldset ng-disabled="isSaving"> ... inputs ...</fieldset>

Il désactivera automatiquement toutes les entrées dans le fieldset.

Ensuite, dans le contrôleur, réglez $scope.isSavingsur trueavant l'appel http et sur falseaprès.

Alexandre Puchkov
la source
On dirait que cela fonctionne vraiment bien même avec <button>! Merci beaucoup Sasha.
YoMan78
9
C'est un bon conseil, bien que malheureusement, l'attribut désactivé sur un ensemble de champs ne soit pas pris en charge dans IE ou Safari w3schools.com/tags/att_fieldset_disabled.asp
kiwiaddo
5
@kiwiaddo Cela fonctionne bien dans IE9 + dans mes tests. Au fait, w3schools.com n'est pas le meilleur site de référence. Mieux vaut vérifier cette page developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset
Alexander Puchkov
3
Bouton de type d'entrée, texte et fichier non désactivés dans IE11 :-(, également le bouton est grisé mais le gestionnaire de ng-click angulaire se déclenche toujours.
Sebastian
3
@ im1dermike vous avez raison, cela ne fonctionne pas dans IE en effet. Le champ est visuellement défini comme désactivé, mais l'utilisateur peut toujours interagir avec lui et le modifier comme s'il était activé. Il y a un bogue dans IE pour cela déjà soumis et il a été corrigé, mais pas encore expédié. Il sera disponible dans la prochaine version majeure d'IE connect.microsoft.com/IE/feedbackdetail/view/962368/…
Alexander Puchkov
-5

Il existe une solution simple dans les navigateurs modernes:

  1. définir une classe css

    .disabled {
      pointer-events: none;
      ... ...
    }
  2. ajouter cette classe à ng-form

    <ng-form data-ng-class="{ 'disabled': isSaving }"> ... inputs ... </ng-form>

Voici legraphique de prise en charge des événements de pointeur .

Remarque: même si vous définissez pointer-events: none, vous pouvez toujours tabuler pour entrer l'élément avec votre clavier.

Raoh
la source