Eu tenho uma tabela que é criada usando ng-repeat. Desejo adicionar validação a cada elemento da tabela. O problema é que cada célula de entrada tem o mesmo nome que a célula acima e abaixo dela. Tentei usar o {{$index}}
valor para nomear as entradas, mas, apesar de os literais de string em HTML parecerem corretos, ele está funcionando agora.
Aqui está o meu código a partir de agora:
<tr ng-repeat="r in model.BSM ">
<td>
<input ng-model="r.QTY" class="span1" name="QTY{{$index}}" ng-pattern="/^[\d]*\.?[\d]*$/" required/>
<span class="alert-error" ng-show="form.QTY{{$index}}.$error.pattern"><strong>Requires a number.</strong></span>
<span class="alert-error" ng-show="form.QTY{{$index}}.$error.required"><strong>*Required</strong></span>
</td>
</tr>
Eu tentei remover o {{}}
índice, mas isso também não funciona. A partir de agora, a propriedade de validação da entrada está funcionando corretamente, mas a mensagem de erro não é exibida.
Alguém tem alguma sugestão?
Editar: além das ótimas respostas abaixo, aqui está um artigo de blog que aborda esse problema com mais detalhes: http://www.thebhwgroup.com/blog/2014/08/angularjs-html-form-design-part-2 /
fonte
Respostas:
O AngularJS depende de nomes de entrada para expor erros de validação.
Infelizmente, a partir de hoje, não é possível (sem o uso de uma diretiva personalizada) gerar dinamicamente o nome de uma entrada. De fato, verificando os documentos de entrada , podemos ver que o atributo name aceita apenas uma string.
Para resolver o problema do 'nome dinâmico', você precisa criar um formulário interno (consulte ng-form ) :
A outra alternativa seria escrever uma diretiva personalizada para isso.
Aqui está o jsFiddle mostrando o uso do ngForm: http://jsfiddle.net/pkozlowski_opensource/XK2ZT/2/
fonte
ng-form
elementos DOM, portanto o link para a outra pergunta SO não é relevante aqui.ng-repeat
estiver ligadotable tr
, precisará usar ong-form="myname"
attr.Desde que a pergunta foi feita, a equipe Angular resolveu esse problema, possibilitando a criação dinâmica de nomes de entrada.
Com a versão Angular 1.3 e posterior, agora você pode fazer isso:
Demo
O Angular 1.3 também introduziu o ngMessages, uma ferramenta mais poderosa para validação de formulários. Você pode usar a mesma técnica com ngMessages:
fonte
$valid
propriedade para a entrada fica incorretamentefalse
Se você não quiser usar o ng-form, poderá usar uma diretiva personalizada que alterará o atributo name do formulário. Coloque esta diretiva como um atributo no mesmo elemento que o seu ng-model.
Se você estiver usando outras diretivas em conjunto, tenha cuidado para que elas não possuam a propriedade "terminal" definida, caso contrário, essa função não poderá ser executada (desde que tenha a prioridade -1).
Por exemplo, ao usar esta diretiva com ng-options, você deve executar este monkeypatch de uma linha: https://github.com/AlJohri/bower-angular/commit/eb17a967b7973eb7fc1124b024aa8b3ca540a155
Costumo achar útil usar o ng-init para definir o $ index como um nome de variável. Por exemplo:
Isso altera sua expressão regular para:
Se você tiver várias repetições ng aninhadas, agora poderá usar esses nomes de variáveis em vez de $ parent. $ Index.
Definição de "terminal" e "prioridade" das diretivas: https://docs.angularjs.org/api/ng/service/ $ compile # directory-definition-object
Comentário do Github sobre a necessidade do monkeypatch da opção ng: https://github.com/angular/angular.js/commit/9ee2cdff44e7d496774b340de816344126c457b3#commitcomment-6832095 https://twitter.com/aljohri/status/482963541520314369
ATUALIZAR:
Você também pode fazer isso funcionar com o ng-form.
fonte
Use a diretiva ng-form dentro da tag na qual você está usando a diretiva ng-repeat. Você pode usar o escopo criado pela diretiva ng-form para fazer referência a um nome genérico. Por exemplo:
Crédito para: http://www.benlesh.com/2013/03/angular-js-validating-form-elements-in.html
fonte
ng-form="formName"
a tag que tem ng-repeat ... ele trabalhou como um encanto :)Exemplo mais complexo adicionado com "validação personalizada" na lateral do controlador http://jsfiddle.net/82PX4/3/
fonte
Examinando essas soluções, a fornecida por Al Johri acima é a mais próxima das minhas necessidades, mas sua diretiva era um pouco menos programável do que eu queria. Aqui está minha versão de suas soluções:
Essa solução permite passar apenas uma expressão de gerador de nome para a diretiva e evitar o bloqueio da substituição de padrão que ele estava usando.
Inicialmente, também tive problemas com essa solução, pois ela não mostrava um exemplo de uso na marcação, então aqui está como eu a usei.
Eu tenho um exemplo de trabalho mais completo no github .
fonte
a validação está funcionando com ng repeat se eu usar a seguinte sintaxe
scope.step3Form['item[107][quantity]'].$touched
Não sei se é uma prática recomendada ou a melhor solução, mas funcionafonte
Com base na resposta de pkozlowski.opensource , adicionei uma maneira de ter nomes de entrada dinâmicos que também funcionam com ngMessages . Observe a
ng-init
parte nong-form
elemento e o uso defurryName
.furryName
torna-se o nome da variável que contém o valor da variável para oinput
'sname
atributo.fonte
É tarde demais, mas pode ajudar alguém
fromname[uniquname].$error
Código de amostra:
Veja a demonstração de trabalho aqui
fonte
Se o uso do índice ng-repeat $ funcionar assim
e
temos que mostrar o ng-show no ng-padrão
fonte
É possível e aqui está como eu faço a mesma coisa com uma tabela de entradas.
enrole a mesa em uma forma como essa
Então é só usar isso
Eu tenho um formulário com diretivas multi-aninhadas que todos contêm entradas, seleções, etc.
Isto é como usar a diretiva:
Nota: você pode adicionar e indexar à concatenação de cadeias se precisar serializar talvez uma tabela de entradas; Foi o que eu fiz.
Isso deve lidar com muitas situações em que você simplesmente não sabe onde estará o formulário. Ou talvez você tenha formulários aninhados, mas por algum motivo você deseja anexar esse nome de entrada a dois formulários acima? Bem, basta passar o nome do formulário ao qual você deseja anexar o nome da entrada.
O que eu queria era uma maneira de atribuir valores dinâmicos a entradas que eu nunca conhecerei e, em seguida, basta chamar $ scope.myFormName. $ Valid.
Você pode adicionar qualquer outra coisa que desejar: mais tabelas, mais entradas de formulário, formulários aninhados, o que quiser. Basta passar o nome do formulário no qual você deseja validar as entradas. Em seguida, no formulário, envie se o $ scope.yourFormName. $ Valid
fonte
Isso fará com que o nome no ng-repeat seja separado separadamente na validação do formulário.
Mas tive problemas para procurar na mensagem de validação, então tive que usar um ng-init para resolver uma variável como chave do objeto.
fonte
Aqui está um exemplo de como faço isso, não sei se é a melhor solução, mas funciona perfeitamente.
Primeiro, codifique em HTML. Veja a classe ng, está chamando a função hasError. Veja também a declaração do nome da entrada. Eu uso o $ index para criar diferentes nomes de entrada.
E agora, aqui está a função hasError:
fonte
Minhas exigências eram um pouco diferentes das solicitadas na pergunta original, mas espero poder ajudar alguém que está passando pelo mesmo problema que eu.
Eu tive que definir se um campo era obrigatório ou não com base em uma variável de escopo. Então, basicamente, tive que definir
ng-required="myScopeVariable"
(que é uma variável booleana).fonte