Ao enviar um formulário em AngularJS e usar a funcionalidade de lembrar senha do navegador e, em uma tentativa de login subsequente, você permitir que o navegador preencha o formulário de login com o nome de usuário e a senha, o $scope
modelo não será alterado com base no preenchimento automático.
O único hack sujo que encontrei é usar a seguinte diretiva:
app.directive("xsInputSync", ["$timeout" , function($timeout) {
return {
restrict : "A",
require: "?ngModel",
link : function(scope, element, attrs, ngModel) {
$timeout(function() {
if (ngModel.$viewValue && ngModel.$viewValue !== element.val()) {
scope.apply(function() {
ngModel.$setViewValue(element.val());
});
}
console.log(scope);
console.log(ngModel.$name);
console.log(scope[ngModel.$name]);
}, 3000);
}
};
}]);
O problema é que o ngModel.$setViewValue(element.val());
não altera o modelo nem a visualização com base no element.val()
valor retornado. Como posso fazer isso?
javascript
mvvm
angularjs
lucassp
fonte
fonte
Respostas:
Aparentemente, este é um problema conhecido do Angular e está aberto no momento
Não tenho certeza do que você poderia fazer aqui além de algum tipo de solução que está tentando. Parece que você está no caminho certo. Não consegui fazer meu navegador tentar lembrar a senha do seu plunk, então não tenho certeza se isso vai funcionar, mas dê uma olhada:
Acho que você só precisa simplificar um pouco sua abordagem. A única coisa que eu definitivamente recomendo é verificar
ngModel.$pristine
e certificar-se de que você não está substituindo a entrada de algum usuário pobre. Além disso, 3 segundos provavelmente é muito tempo. Você não deveria ter que chamar $ apply () em um $ timeout, BTW, ele deveria enfileirar um $ digest para você automaticamente.O verdadeiro problema: seu navegador vai bater o Angular na execução? E o meu navegador?
Esta é provavelmente uma guerra impossível de vencer, e é por isso que Angular (ou Knockout) não foi capaz de resolvê-la prontamente. Não há garantia do estado dos dados em sua entrada no momento da execução inicial da diretiva. Nem mesmo no momento da inicialização do Angular ... Portanto, é um problema complicado de resolver.
fonte
Aqui está uma solução que é muito menos hacky do que outras soluções apresentadas e é semanticamente adequada para AngularJS: http://victorblog.com/2014/01/12/fixing-autocomplete-autofill-on-angularjs-form-submit/
Em seguida, basta anexar a diretiva ao seu formulário:
fonte
Você não precisa usar um
$timeout
ou algo assim. Você pode usar um sistema de eventos.Acho que é mais angular e não depende de jQuery ou captura de evento personalizado.
Por exemplo, em seu manipulador de envio:
E então você pode ter uma
autofill
diretiva como esta:Finalmente, seu HTML será como:
fonte
Não há necessidade de hackear mais! Angular dev tbosch fez um polyfill que aciona um evento de alteração quando o navegador altera os campos do formulário sem acionar um evento de alteração:
https://github.com/tbosch/autofill-event
Por enquanto, eles não vão construir isso no código Angular, já que esta é uma correção de bug para o navegador e também funciona sem Angular (por exemplo, para aplicativos jQuery simples).
"O polyfill verificará as alterações no carregamento do documento e também quando uma entrada for deixada (apenas no mesmo formulário). No entanto, você pode acionar a verificação manualmente se desejar.
O projeto tem testes de unidade, bem como testes semiautomáticos, então finalmente temos um lugar para coletar todos os diferentes casos de uso junto com as configurações de navegador necessárias.
Observação: este polyfill funciona com aplicativos AngularJS simples, com aplicativos AngularJS / jQuery, mas também com aplicativos jQuery simples que não usam Angular. "
Pode ser instalado com:
Adicione o script
autofill-event.js
após jQuery ou Angular em sua página.Isso fará o seguinte:
API (para acionar manualmente a verificação):
$el.checkAndTriggerAutoFillEvent()
: Execute a verificação de todos os elementos DOM no elemento jQuery / jQLite fornecido.Como funciona
Lembre-se de todas as mudanças nos elementos de entrada pelo usuário (ouvindo eventos de mudança) e também por JavaScript (interceptando $ el.val () para elementos jQuery / jQLite). Esse valor alterado é armazenado no elemento em uma propriedade privada.
Verificando um elemento para preenchimento automático: Compare o valor atual do elemento com o valor lembrado. Se for diferente, acione um evento de mudança.
Dependências
AngularJS ou jQuery (funciona com um ou ambos)
Mais informações e fontes na página do github .
A edição original do Angular nº 1460 no Github pode ser lida aqui.
fonte
ngModelOptions
combinado comautofill-event
significa que agora você pode especificarchange
como um dosupdateOn
eventos para garantir que seu modelo esteja sincronizado corretamente.Código sujo, verifique se o problema https://github.com/angular/angular.js/issues/1460#issuecomment-18572604 foi corrigido antes de usar este código. Esta diretiva dispara eventos quando o campo é preenchido, não apenas antes do envio (é necessário se você tiver que lidar com a entrada antes do envio)
fonte
Parece uma solução clara e direta. Não é necessário jQuery.
ATUALIZAR:
fonte
$pristine
antes de alterá-lo e, depois de alterá-lo, mantenha seu$pristine
estado. Caso contrário, você descobrirá que se um formulário for carregado sem dados de preenchimento automático, a diretiva acima ainda atualizará o modelo e, subsequentemente, o fará,dirty
embora o controle do formulário ainda deva ser considerado intocado. exemplo aqui, usando sua diretiva. Comentei o código que adicionaria a ele: jsfiddle.net/OACDesigns/L8Sja/4scope:true
deveria serscope:{}
Solução 1 [usando $ timeout]:
Diretriz:
HTML:
Solução 2 [Usando eventos angulares]:
Ref: a resposta de Becko
Diretriz:
HTML:
Solução 3 [Usando chamadas de método de retransmissão]:
Diretriz:
HTML:
fonte
model.$valid
da diretiva retorna true antes e depois$setViewValue
, mas o elemento ainda está com ang-invalid
classeBem, a maneira mais fácil é emular o comportamento do navegador, então se houver um problema com o evento de mudança, basta dispará-lo você mesmo. Muito mais simples.
Diretriz:
HTML:
Você pode fazer algumas variações, como colocar a diretiva no formulário e disparar o evento em todas as entradas com a classe .dirty no envio do formulário.
fonte
Este é o jeito jQuery:
Esta é a maneira angular:
HTML
fonte
triggerHandler('input')
deve estar ok se você não tiver jquery desenvolvidoAqui está outra solução alternativa que é menos hacky, mas requer algum código extra no controlador.
HTML:
Diretiva (CoffeeScript):
Controlador:
fonte
Esta é a única solução que encontrei que permitiu que todas as minhas validações Angular funcionassem conforme planejado, incluindo o botão de habilitar / desabilitar. Instala com caramanchão e 1 tag de script. Bazinga!
https://github.com/tbosch/autofill-event
fonte
Alterar o valor do modelo, em vez de usar uma função de tempo limite, funcionou para mim.
Aqui está o meu código:
fonte
Solução alternativa de uma linha no manipulador de envio (requer jQuery):
fonte
Eu forço um $ setValue (val ()) no envio: (funciona sem jQuery)
fonte
Eu sou muito novo no Angularjs, mas encontrei uma solução simples para esse problema => Forçar o Angular a reavaliar a expressão ... mudando-a! (é claro que você precisa se lembrar do valor inicial para reverter para o estado inicial). Esta é a maneira como funciona na função do controlador para enviar o formulário:
onde, é claro, o valor inserido em sua entrada de senha foi definido pelo Windows e não pelo usuário.
fonte
Você pode tentar este código:
fonte
Uma pequena modificação nesta resposta ( https://stackoverflow.com/a/14966711/3443828 ): use um intervalo $ em vez de um $ timeout para não ter que correr contra o navegador.
fonte
Essa é a solução que acabei usando nos meus formulários.
E o modelo do formulário será
Desta forma, consegui executar qualquer analisador / formatador que tenho em meu ng-model e ter a funcionalidade de envio transparente.
fonte
Solução sem diretivas:
fonte
Esta é uma correção simples que funciona para todos os casos que testei no Firefox e no Chrome. Observe que com a resposta principal (diretiva com tempo limite), tive problemas com -
Essa correção é obviamente muito burra e hacky, mas funciona 100% do tempo -
fonte
$timeout
com$interval
para dar futuro devs a mais contexto pouco e se livrar dos que procuram estranho chamadas recursivas acontecendo láNenhuma dessas soluções funcionou para meu caso de uso. Eu tenho alguns campos de formulário que usam ng-change para observar mudanças. Usando
$watch
não ajuda, pois não é acionado pelo preenchimento automático. Como não tenho o botão de enviar, não há uma maneira fácil de executar algumas das soluções e não obtive sucesso usando intervalos.Acabei desabilitando o preenchimento automático - não é o ideal, mas muito menos confuso para o usuário.
Encontrou a resposta aqui
fonte
Se você estiver usando jQuery, você pode fazer isso no envio do formulário:
HTML:
JS:
fonte
Se você quiser mantê-lo simples, obtenha o valor usando javascript
Em seu controlador js angular:
var username = document.getElementById ('username'). value;
fonte