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?

Christopher Marshall
fonte
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;
Umur Kontacı
fonte
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);
notMyName
fonte
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>
James Fleming
fonte
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.

rahim.nagori
fonte