AngularJS: desativando todos os controles de formulário entre o envio e a resposta do servidor

122

Eu tenho um dilema sobre qual é a melhor (e correta) abordagem se eu quiser desativar os controles de formulário (ou pelo menos torná-los indisponíveis para a interação do usuário) durante um período em que o usuário clica no botão "Salvar" ou "Enviar" e dados viajando pelo fio. Não quero usar o JQuery (o que é mau !!!) e consultar todos os elementos como array (por marcador de classe ou atributo). As idéias que tive até agora são:

  • Marque todos os elementos com a cm-form-controldiretiva personalizada, que assinará duas notificações: "dados enviados" e "dados processados". Em seguida, o código personalizado é responsável por enviar a segunda notificação ou resolver uma promessa.
  • Use promiseTrackerisso (infelizmente!) Impõe para produzir códigos extremamente estúpidos como ng-show="loadingTracker.active()". Obviamente, nem todos os elementos têm ng-disablede eu não quero que o usuário ng-hide/showevite "dançar" os botões.
  • Morda uma bala e ainda usa JQuery

Alguém tem uma idéia melhor? Desde já, obrigado!

ATUALIZADO: A idéia do fieldset funciona. Aqui está um violino simples para aqueles que ainda querem fazer o mesmo 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>

e 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
fonte
qual serviço você está usando para enviar os dados do formulário? $ http ou $ resource?
François Romain
É realmente $ http como eu não preciso lidar com nada de excepcional.
YoMan78
Os conjuntos de campos desativados não funcionam no IE, ou seja, não são uma solução. Eu uso um modal Bootstrap e defino o cenário como estático.
im1dermike
Note-se que no momento da escrita não é um bug , onde fieldsetnão pode ser usado como um recipiente flexbox
George Mauer

Respostas:

283

Coloque todos os seus campos no fieldset e use a diretiva ngDisabled da seguinte maneira:

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

Desabilitará automaticamente todas as entradas dentro do fieldset.

Em seguida, no controlador definido $scope.isSavingcomo trueantes da chamada http e falsedepois.

Alexander Puchkov
fonte
Parece que realmente funciona bem, mesmo com <button>! Muito obrigado Sasha.
YoMan78
9
É uma boa dica, embora, infelizmente, o atributo disabled em um conjunto de campos não é suportado no IE ou Safari w3schools.com/tags/att_fieldset_disabled.asp
kiwiaddo
5
@kiwiaddo Funciona bem no IE9 + nos meus testes. A propósito, o w3schools.com não é o melhor site de referência. Melhor verificar esta página developer.mozilla.org/pt-BR/docs/Web/HTML/Element/fieldset
Alexander Puchkov
3
Botão tipo de entrada, texto e arquivos não desactivado no IE11 :-(, também botão é acinzentado, mas angular ng-click-manipulador ainda incêndios.
Sebastian
3
@ im1dermike você está certo, ele realmente não funciona no IE. O campo possui estilo visual como desativado, mas o usuário ainda pode interagir com ele e editá-lo como se estivesse ativado. Há um bug no IE para isso já enviado e foi corrigido, mas ainda não foi enviado. Ele estará disponível na próxima versão principal do IE, connect.microsoft.com/IE/feedbackdetail/view/962368/…
Alexander Puchkov 10/15
-5

Existe uma solução simples nos navegadores modernos:

  1. definir uma classe css

    .disabled {
      pointer-events: none;
      ... ...
    }
  2. adicione esta classe a ng-form

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

Aqui está ográfico de suporte a eventos de ponteiro .

Nota: mesmo se você definir pointer-events: none, ainda poderá tabular para inserir o elemento com o teclado.

Raoh
fonte