2016-07-15 61 views
0

我已經創造了一些指令,它們幫我檢查輸入的有效性,看起來或多或少像這樣的形式檢索輸入驗證錯誤:從內部指令

app.directive("initialDate", function(){ 
    return{ 
     require: '?ngModel', 
     restrict:"A", 
     link:function(scope, element, attrs, ngModel){ 
      scope.$watch(attrs.ngModel, function() { 
       validate(); 
      }); 
      attrs.$observe('initialDate', function() { 
       validate(); 
      }); 
      var validate = function() { 
       var date = Date.parse(ngModel.$viewValue); 
       var initialDate = Date.parse(attrs.initialDate); 
       ngModel.$setValidity('initial-date', date >= initialDate); 
      } 
     } 
    } 
}); 

現在,我想自定義消息添加到輸入,選擇等等,這些都沒有通過驗證,但我不想一個接一個地用ng-if添加一個span或somethinng(這是我想避免的很多工作)。

我第一次嘗試是創建這樣的指令:所以現在

app.directive("ngInvalid", function(){ 
    restrict:"C", 
    ... 
}); 

但是didn't工作我正嘗試這一

app.directive("input", function(){ 
    return { 
     require:"?ngModel", 
     link:function(scope, element, attrs, ctrl){ 
      scope.$watch(function() { 
       return element.attr('class'); 
      }, function(newVal, oldVal){ 
       if (newVal == oldVal) return;  
       if (element.hasClass("ng-invalid")){ 
        element.parent().append("<span class = 'error' style='color:red'>There was an error</span>"); 
       }else{ 
        element.parent().find(".error").remove(); 
       } 
      }); 
     } 
    } 
}); 

所以,這一個工程(更或更少,它需要更多的工作,嘿嘿),但我將不得不創建一個選擇,textareas等,並對每種類型的錯誤進行一些檢查,如果我想顯示自定義消息。

此外,它真的看起來很髒。我真的覺得一定有什麼事情,我可以說看起來更像這個指令內做到:

... 
link:function(scope, element, attrs, ctrl){ /***element is the input or select or textarea... ***/ 
    if (!element.$isValid){ 
     switch (element.$validationErrors[0]){ 
      case "emailValidation": element.parent().append("<span class = 'error' style='color:red'>Email format not correct</span>"); break; 
      case "initialDate": element.parent().append("<span class = 'error' style='color:red'>Date cannot be previous to {{initialDate}}</span>"); break; 
      case "pattern": element.parent().append("<span class = 'error' style='color:red'>Format incorrect</span>"); break; 
     } 

    } 
} 
... 

我一直在尋找在文檔和瀏覽的一些問題,但主要是我發現需要使用的解決方案表單控制器,我想避免這種情況。

是否有一些方法可以讓我從輸入中檢索錯誤?

編輯

要清楚,let's說,輸入沒有包裝形式的標籤裏面,但股利,或別的東西。我如何訪問輸入指令中的每個錯誤?

+2

看一下ng-messages – dewd

+0

看起來不錯,但並不能解決我想要實現的兩件事:如果我想在每個字段上顯示一個顯示錯誤,則不依賴於使用表單並必須爲每個輸入創建一個組件。 – sergio0983

回答

0

簡答

不,it's無法訪問有效性檢查,而不表單控件。

解決方法

我使用的輸入指令來實現我想要的東西,但它doesn't似乎太高雅了,我(我倒是很喜歡使用文本域影響而不必選擇指令我-定製指令添加到每個領域我想驗證)

(function(){ 
    var lang = navigator.language.substr(0,2) || navigator.userLanguage.substr(0,2); 

    const E_UNKNOWN = 0, 
    E_REQUIRED = 1, 
    E_NAN = 2, 
    E_MIN = 3, 
    E_MAX = 4, 
    E_EMAIL = 5, 
    E_MINLEN = 6, 
    E_MAXLEN = 7, 
    E_PATTERN = 8, 
    E_BLACKLIST = 9, 
    E_EQUAL = 10; 
    E_INITIALDATE = 11; 

    const ERR_MESSAGES = [ 
     {'es':'Error desconocido', 'en':'Unknown Error'}, 
     {'es':'Este campo es obligatorio', 'en':'This field is mandatory'}, 
     {'es':'Este campo debe ser numérico', 'en':'This field should be numeric'}, 
     {'es':'El valor es inferior al mínimo', 'en':'Value is lower than the minimum'}, 
     {'es':'El valor es superior al máximo', 'en':'Value is higher than the maximum'}, 
     {'es':'El formato de email no es válido', 'en':'Email format incorrect'}, 
     {'es':'No cumple longitud mínima', 'en':'Minimum length not matched'}, 
     {'es':'No cumple longitud máxima', 'en':'Maximum length not matched'}, 
     {'es':'El formato no es válido', 'en':'Format incorrect'}, 
     {'es':'Este valor no está permitido', 'en':'This value is not allowed'}, 
     {'es':'Los campos no coinciden', 'en':'Fields doesn´t match'}, 
     {'es':'La fecha es anterior a la fecha inicial', 'en':'This date is previous to the initial date'}, 
    ]; 

    var lang = navigator.language.substr(0,2) || navigator.userLanguage.substr(0,2); 

    app.directive("input", function(){ 
     return { 
      scope:{}, 
      link:function(scope, element, attrs, ctrl, ngModel){ 
       scope.blurred = false; 
       element[0].addEventListener("blur", function(){ 
        scope.blurred = true; 
        element.parent().find(".error").remove(); 
        checkValidity(); 
       }); 

       var checkValidity = function(){ 
        var classList = element.attr('class'); 
        if (!classList) return; 
        var matches = classList.match(/ng-invalid-(.*?)(\s|$)/); 
        if (matches == null) return; 
        if (!(1 in matches)) return; 

        var $err = matches[1]; 
        var $errMessage = ""; 

        switch($err){ 
         case "required": $errMessage = ERR_MESSAGES[E_REQUIRED][lang]; break; 
         case "number": $errMessage = ERR_MESSAGES[E_NAN][lang]; break; 
         case "min": $errMessage = ERR_MESSAGES[E_MIN][lang]; break; 
         case "max": $errMessage = ERR_MESSAGES[E_MAX][lang]; break; 
         case "email": $errMessage = ERR_MESSAGES[E_EMAIL][lang]; break; 
         case "minlength": $errMessage = ERR_MESSAGES[E_MINLEN][lang]; break; 
         case "maxlength": $errMessage = ERR_MESSAGES[E_MAXLEN][lang]; break; 
         case "pattern": $errMessage = ERR_MESSAGES[E_PATTERN][lang]; break; 
         case "blacklist": $errMessage = ERR_MESSAGES[E_BLACKLIST][lang]; break; 
         case "equals": $errMessage = ERR_MESSAGES[E_EQUAL][lang]; break; 
         case "initial-date": $errMessage = ERR_MESSAGES[E_INITIALDATE][lang]; break; 
         default: $errMessage = ERR_MESSAGES[E_UNKNOWN][lang]; break; 
        } 

        if (element.hasClass("ng-invalid")){ 
         element.parent().append("<span class = 'error'>"+$errMessage+"</span>"); 
        } 
       } 
      } 
     } 
    }); 
})(); 

這裏是一個鏈接到一個工作codepen:http://codepen.io/sergio0983/pen/AXxNpN?editors=1111

出於某種原因,在codepen中,如果我不在角元素上使用$選擇器,錯誤不會被刪除()

0

我發佈的上一個方法有一些問題。對班級的監視並不像預期的那樣工作,當班級實際發生變化時並沒有被解僱,而是當下一個輸入字符被輸入時。例如,所需的錯誤是在空白後在輸入中引入了一個新的字符,並且控制檯中的日誌和檢查器中的類是不同的(可能是有角度的錯誤)。

反正,我已經找到我認爲是更好的解決方案:哦,it's實際上可以訪問有效性檢查時的控制是不是一個形式的標籤

That's裏面包裹代碼(我didn't添加一個模糊賬了,但應該很容易)

var errMsgDirective = function(){ 
    return{ 
     restrict:"E", 
     require:"?ngModel", 
     link:function(scope, element, attrs, ctrl, ngModel){ 
      if (!attrs.ngModel) return; 

      var lang = navigator.language.substr(0,2) || navigator.userLanguage.substr(0,2); 
      const E_UNKNOWN = 0, E_REQUIRED = 1, E_NAN = 2, E_MIN = 3, E_MAX = 4, E_EMAIL = 5, E_MINLEN = 6, E_MAXLEN = 7, E_PATTERN = 8, E_BLACKLIST = 9, E_EQUAL = 10; E_INITIALDATE = 11;  
      const ERR_MESSAGES = [ 
       {'es':'Error desconocido', 'en':'Unknown Error'}, 
       {'es':'Este campo es obligatorio', 'en':'This field is mandatory'}, 
       {'es':'Este campo debe ser numérico', 'en':'This field should be numeric'}, 
       {'es':'El valor es inferior al mínimo', 'en':'Value is lower than the minimum'}, 
       {'es':'El valor es superior al máximo', 'en':'Value is higher than the maximum'}, 
       {'es':'El formato de email no es válido', 'en':'Email format incorrect'}, 
       {'es':'No cumple longitud mínima', 'en':'Minimum length not matched'}, 
       {'es':'No cumple longitud máxima', 'en':'Maximum length not matched'}, 
       {'es':'El formato no es válido', 'en':'Format incorrect'}, 
       {'es':'Este valor no está permitido', 'en':'This value is not allowed'}, 
       {'es':'Los campos no coinciden', 'en':'Fields doesn´t match'}, 
       {'es':'La fecha es anterior a la fecha inicial', 'en':'This date is previous to the initial date'}, 
      ]; 
      var checkValidity = function(){ 
       if (!ctrl.$touched) return; 


       var errors = []; 
       for (var i in ctrl.$error){ 
        if (ctrl.$error[i] == false) continue;   
        switch (i){ 
         case "required": errors.push(ERR_MESSAGES[E_REQUIRED][lang]); break; 
         case "number": errors.push(ERR_MESSAGES[E_NAN][lang]); break; 
         case "min": errors.push(ERR_MESSAGES[E_MIN][lang]); break; 
         case "max": errors.push(ERR_MESSAGES[E_MAX][lang]); break; 
         case "email": errors.push(ERR_MESSAGES[E_EMAIL][lang]); break; 
         case "minlength": errors.push(ERR_MESSAGES[E_MINLEN][lang]); break; 
         case "maxlength": errors.push(ERR_MESSAGES[E_MAXLEN][lang]); break; 
         case "pattern": errors.push(ERR_MESSAGES[E_PATTERN][lang]); break; 
         case "blacklist": errors.push(ERR_MESSAGES[E_BLACKLIST][lang]); break; 
         case "equals": errors.push(ERR_MESSAGES[E_EQUAL][lang]); break; 
         case "initial-date": errors.push(ERR_MESSAGES[E_INITIALDATE][lang]); break; 
         default: errors.push(ERR_MESSAGES[E_UNKNOWN][lang]); break; 
        } 
       } 

       element.parent().find(".error").remove(); 
       if (errors.length == 0){ 

       }else{ 
        $errMessage = errors.join("; "); 
        element.parent().append("<span class = 'error'>"+$errMessage+"</span>"); 
       } 
      } 

      scope.$watch(function(){ 
       return JSON.stringify(ctrl.$error); 
      }, function(){ 
       checkValidity(); 
      }); 

      scope.$watch(function(){ 
       return ctrl.$touched; 
      }, function(){ 
       checkValidity(); 
      }) 
     } 
    } 
} 

app.directive("input", errMsgDirective); 
app.directive("textarea", errMsgDirective); 
app.directive("select", errMsgDirective); 

有一些事情我想指出:

1:我可以訪問相對於裏面的每個控制所有錯誤指令與ctr l。$錯誤(爲了上帝的緣故,爲什麼在所有堆棧溢出中沒有一個單一的答案,說你可以用。$ error?來訪問控制錯誤。 ¬¬)

第二:我有一個真正的困難時期將是工作的手錶:我嘗試了所有的以下內容:

scope.$watch(attrs.ngModel, function(){...}) //This one did not work because the model doesn´t change when the validity checks are not met 
scope.$watch(ctrl.$valid, function(){...}) //Never fired 
scope.$watch(ctrl.$invalid, function(){...}) //Never fired 
scope.$watch(ctrl.$error, function(){...}) //Never fired 
scope.$watch(function(){ return ctrl.$error }, function(){...}) //Never fired 
scope.$watch(function(){ return JSON.stringify(ctrl.$error) }, function(){...}) //BINGO!!! 

在這裏你可以看到它的工作:

http://codepen.io/sergio0983/pen/ZOvPvW?editors=1011