Usando $ setValidity dentro de un controlador

78

Estoy tratando de hacer una validación en el cambio de archivo. Aquí está mi código:

Ver / Plantilla

<input type="file" name="file" id="file"  
       onchange="angular.element(this).scope().setFile(this)" 
       required />

<span class="error" ng-show="myForm.file.$error.required">Error</span>
<span class="error" ng-show="myForm.file.$error.size">Selected file is too large</span>
<span class="error" ng-show="myForm.file.$error.filetype">Unsupported File type</span>

Controlador

angular.module("myapp").controller("myctrl", function($scope) {
  $scope.setFile = function(element) {
    $scope.$apply(function($scope) {
      var fileObject = element.files[0];
      $scope.file.fileType = 
         fileObject.type.toUpperCase().substring(fileObject.type.indexOf("/") + 1);

      // Validation
      if (!$scope.isValidFileType($scope.file.fileType)) {
        myForm.file.$setValidity("myForm.file.$error.filetype", false);
      }

      if (fileObject.size > 1000*1000*10) {
        myForm.file.$setValidity("myForm.file.$error.size", false);
      }
    });
  };

  $scope.isValidFileType = function(fileExtension) {
    var supportedExtensions = ["doc", "docx", "ppt", "pptx", "jpg", "gif", "png"]; // etc.
    return (jQuery.inArray(fileExtension, supportedExtensions) > -1);
  }
});

Pero en este momento la llamada a $setValidityno está funcionando.
¿Alguna idea?

Churk
fuente

Respuestas:

129

Esta línea:

myForm.file.$setValidity("myForm.file.$error.size", false);

Debiera ser

$scope.myForm.file.$setValidity("size", false);
Ben Lesh
fuente
1
¿Puede esto funcionar igual dentro de una función de enlace? Recibo $ setValidity no es una función
Winnemucca
17

$ setValidity debe llamarse en ngModelController. Dentro del controlador, creo que eso significa $scope.myForm.file.$setValidity().

Consulte también la sección "Validación personalizada" en la página Formularios , si aún no lo ha hecho.

Además, para el primer argumento de $ setValidity, use solo 'filetype' y 'size'.

Mark Rajcok
fuente
1
¡Decir ah! Publiqué lo mismo al mismo tiempo.
Ben Lesh
1
@blesh, ahora son dos días seguidos.
Mark Rajcok
En realidad, lo que señalaron era correcto, cometí un error en setValidity (). Pero ese no era mi problema, mi problema era el del alcance. Estaba llamando a esto en el nivel <input> mientras que el formulario está fuera de alcance. De hecho, tuve que hacer esto:$scope.$on('$includeContentLoaded', function(e) { $scope.myForm = e.targetScope.myForm;});
Churk
2

Una solución mejor y optimizada para mostrar múltiples mensajes de validación para un solo elemento sería así.

<div ng-messages="myForm.file.$error" ng-show="myForm.file.$touched">
 <span class="error" ng-message="required"> <your message> </span>
 <span class="error" ng-message="size"> <your message> </span>
 <span class="error" ng-message="filetype"> <your message> </span>
</div>

El código del controlador debe ser el sugerido por @ Ben Lesh

Alvin Chettiar
fuente