AngularJS: deshabilitar todos los controles de formulario entre enviar y la respuesta del servidor

122

Tengo un dilema sobre cuál es el mejor enfoque (y el correcto) si deseo deshabilitar los controles de formulario (o al menos hacer que no estén disponibles para la interacción del usuario) durante un período de tiempo cuando el usuario hace clic en el botón "Guardar" o "Enviar" y datos viajando a través del cable. No quiero usar JQuery (¡lo cual es malo!) Y consultar todos los elementos como matriz (por clase o marcador de atributo) Las ideas que tenía hasta ahora son:

  • Marque todos los elementos con cm-form-controluna directiva personalizada que se suscribirá para 2 notificaciones: "datos enviados" y "datos procesados". Luego, el código personalizado es responsable de enviar una segunda notificación o resolver una promesa.
  • Use promiseTrackereso (¡desafortunadamente!) Aplica para producir código extremadamente estúpido como ng-show="loadingTracker.active()". Obviamente, no todos los elementos tienen ng-disabledy no quiero que el usuario ng-hide/showevite los botones "bailando".
  • Muerde una bala y aún usa JQuery

¿Alguien tiene una idea mejor? ¡Gracias por adelantado!

ACTUALIZADO: La idea del conjunto de campos sí funciona. Aquí hay un violín simple para aquellos que todavía quieren hacer lo mismo 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>

y 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
fuente
¿Qué servicio está utilizando para enviar los datos desde el formulario? $ http o $ resource?
François Romain
En realidad es $ http ya que no necesito lidiar con nada pendiente.
YoMan78
Los conjuntos de campos deshabilitados no funcionan en IE, es decir, no son una solución. Uso un modal de Bootstrap y configuro el fondo como estático.
im1dermike
Tenga en cuenta que, al momento de escribir, hay un error que fieldsetno se puede usar como un contenedor flexbox
George Mauer

Respuestas:

283

Envuelva todos sus campos en el conjunto de campos y use la directiva ngDisabled de esta manera:

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

Deshabilitará automáticamente todas las entradas dentro del conjunto de campos.

Luego, en controlador configurado $scope.isSavingpara trueantes http llamada y falsedespués.

Alexander Puchkov
fuente
¡Parece que realmente funciona bien incluso con <button>! Muchas gracias Sasha.
YoMan78
9
Es un buen consejo, aunque desafortunadamente el atributo deshabilitado en un conjunto de campos no es compatible con IE o Safari w3schools.com/tags/att_fieldset_disabled.asp
kiwiaddo
55
@kiwiaddo Funciona bien en IE9 + en mis pruebas. Por cierto, w3schools.com no es el mejor sitio web de referencia. Mejor revise esta página developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset
Alexander Puchkov
3
El botón de tipo de entrada, el texto y el archivo no están deshabilitados en IE11 :-(, también el botón está atenuado pero el controlador angular ng-click-handler aún se activa.
Sebastian
3
@ Im1dermike tienes razón, no funciona en IE de hecho. El campo tiene un estilo visual como deshabilitado, pero el usuario aún puede interactuar con él y editarlo como si estuviera habilitado. Hay un error en IE para esto ya enviado y se corrigió, pero aún no se envió. Estará disponible en la próxima versión principal de IE connect.microsoft.com/IE/feedbackdetail/view/962368/…
Alexander Puchkov
-5

Hay una solución simple en los navegadores modernos:

  1. definir una clase css

    .disabled {
      pointer-events: none;
      ... ...
    }
  2. agrega esta clase a ng-form

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

Aquí está latabla de soporte de eventos de puntero .

Nota: incluso si configura pointer-events: none, aún puede tabular al elemento de entrada con su teclado.

Raoh
fuente