AngularJS: Como faço para definir manualmente a entrada $ valid no controlador?


92

Usando o plug- in TokenInput e usando a validação de formController integrada do AngularJS.

No momento, estou tentando verificar se o campo contém texto e, em seguida, definir o campo para válido se contiver. O problema de usar o plug-in é que ele cria sua própria entrada e, em seguida, um ul + li para configurar.

Tenho acesso a addItem (formname) e meus recursos no controlador, só preciso configurá-lo como $ valid.

Markup.

<form class="form-horizontal add-inventory-item" name="addItem">
     <input id="capabilities" name="capabilities" token-input data-ng-model="inventoryCapabilitiesAutoComplete" data-on-add="addCapability()" data-on-delete="removeCapability()" required>
     <div class="required" data-ng-show="addItem.capabilities.$error.required" title="Please enter capability."></div>
</form>

JS.

$scope.capabilityValidation = function (capability) {
  if (capability.name !== "") {
    addItem.capabilities.$valid = true;
    addItem.capabilities.$error.required = false;
  } else {
    addItem.capabilities.$valid = false;
    addItem.capabilities.$error.required = true;
  }
};

Estou executando a função capacityValidation quando TokenInput tem algo inserido e passando no objeto.

EDITAR:

Descobri que o ng-model em minha entrada faz coisas e obtém os resultados do preenchimento automático, e é por isso que não consigo fazer o ng-valid funcionar, pois ele é baseado no modelo.

$scope.inventoryCapabilitiesAutoComplete = {
  options: {
    tokenLimit: null
  },
  source: urlHelper.getAutoComplete('capability')
};

Eu não escrevi esta implementação de preenchimento automático. Existe outra maneira de fazer isso onde eu teria acesso ao atributo ng-model e movesse a função do modelo para outro lugar?


1
Já que seu plugin está criando sua própria entrada, e você escreveu uma função para fazer sua própria validação, por que não usar sua própria propriedade $ scope para validação também: <div ... data-ng-show="capabilities_error" ...> Em outras palavras, há uma razão para você querer / precisar usar FormController?
— Mark Rajcok

2
Como todos os meus outros formulários estão usando, gostaria de manter o controle que ele oferece. A entrada criada pelo plug-in na verdade define o valor em minha entrada original, que eu preciso verificar em minha validação, mas não atualiza o formController quando há um valor inserido.
— Christopher Marshall

Encurtei a marcação de propósito para isolar a entrada. Tenho mais um monte de entradas neste mesmo formulário.
— Christopher Marshall

1
OK. Você tentou addItem.capabilities.$valid = truee / ou definir addItem.capabilities. $ Error.required como true ou false, conforme apropriado?
— Mark Rajcok

Eu tentei ambos. Vou atualizar minha pergunta para mostrar a você. O $ valid e $ error.required é mostrado como indefinido em meu ponto de interrupção no controlador, mas addItem.capabilities ainda tem dados.
— Christopher Marshall

Respostas:


150

Você não pode alterar diretamente a validade de um formulário. Se todas as entradas descendentes forem válidas, o formulário é válido; se não, não é.

O que você deve fazer é definir a validade do elemento de entrada. Igual a;

addItem.capabilities.$setValidity("youAreFat", false);

Agora a entrada (e portanto o formulário) é inválida. Você também pode ver qual erro causa a invalidação.

addItem.capabilities.errors.youAreFat == true;

1
E se capabilitiesfor uma variável? Eu tenho uma matriz que contém nomes de entrada e quero fazer um loop dentro da matriz e defini-los inválidos um por um: /
— lightalex

1
O que você quer dizer com variável? Ele está diretamente vinculado ao próprio formulário, não aos valores no formulário. Ele usa o nameatributo do formulário e o atributo de entrada id. Isso é diferente dos valores definidos porngModel
— Umur Kontacı

11
Eu encontrei a solução, mas era o que eu queria dizer:$scope.addItem['myVariableName'].$setValidity("youAreFat", false);
— lightalex

Depois disso, parece que alguns campos de entrada não são mais validados na mudança ou desfoque
— Leonardo

4
No angular 1.4.7 e tive que prefixar este código com $ scope ..$scope.addItem.capabilities.$setValidity("youAreFat", false);
— Graham T

60

As respostas acima não me ajudaram a resolver meu problema. Após uma longa pesquisa, encontrei esta solução parcial .

Finalmente resolvi meu problema com este código para definir o campo de entrada manualmente como ng-invalid (para definir como ng-valid, defina-o como 'true'):

$scope.myForm.inputName.$setValidity('required', false);

3
Eu fiz a mesma coisa e funcionou muito bem. Mas agora estou com alguns problemas para revalidar o mesmo campo. Não muda para o estado alterado, o que é muito irritante. Eu uso ng-model-options = "{updateOn: 'submit'}" para validar ao clicar em um botão. Alguma opinião sobre isso?
— OliverKK

1
@OliverKK você precisará invocar $setValiditycom truecomo o segundo parâmetro sempre que a entrada for válida.
— Bernhard Hofmann

10
não faz sentido usar o rootcope, deve ser apenas o scope
— Ryan M

1
Tentei uma solução semelhante, mas o problema que encontrei é que se eu tentar alterar o valor do controle no formulário, ele permanece inválido. No meu caso, esse controle é uma diretiva com o select interno. Se eu definir o inválido para minha diretiva (que é a forma ng), não poderei remover esse status inválido.
— Naomi

18

Me deparei com este post com um problema semelhante. Minha correção foi adicionar um campo oculto para manter meu estado inválido para mim.

<input type="hidden" ng-model="vm.application.isValid" required="" />

No meu caso, tive um bool anulável em que uma pessoa teve que selecionar um dos dois botões diferentes. se a resposta for sim, uma entidade é adicionada à coleção e o estado do botão muda. Até que todas as questões sejam respondidas (um dos botões em cada um dos pares tem um clique) o formulário não é válido.

vm.hasHighSchool = function (attended) { 
  vm.application.hasHighSchool = attended;
  applicationSvc.addSchool(attended, 1, vm.application);
}
<input type="hidden" ng-model="vm.application.hasHighSchool" required="" />
<div class="row">
  <div class="col-lg-3"><label>Did You Attend High School?</label><label class="required" ng-hide="vm.application.hasHighSchool != undefined">*</label></div>
  <div class="col-lg-2">
    <button value="Yes" title="Yes" ng-click="vm.hasHighSchool(true)" class="btn btn-default" ng-class="{'btn-success': vm.application.hasHighSchool == true}">Yes</button>
    <button value="No" title="No" ng-click="vm.hasHighSchool(false)" class="btn btn-default" ng-class="{'btn-success':  vm.application.hasHighSchool == false}">No</button>
  </div>
</div>

2

É muito simples. Por exemplo: em seu controlador JS use isto:

$scope.inputngmodel.$valid = false;

ou

$scope.inputngmodel.$invalid = true;

ou

$scope.formname.inputngmodel.$valid = false;

ou

$scope.formname.inputngmodel.$invalid = true;

Tudo funciona para mim para requisitos diferentes. Informe-se se isso resolver seu problema.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.