2014-01-09 145 views
0

我正在嘗試爲自定義輸入組件創建一些自定義驗證。AngularJS:控制器 - 指令雙向通信

自定義輸入的指令將充當黑盒,因此我可以從控制器添加我想要的驗證。

要做到這一點我想補充的指令的屬性,所謂的「驗證」,PE:

<custom-input validations="checkEmail() checkIsNotUsed()" type="text" placeholder="Email"></custom-input> 

有了這個例子,我可以從控制器定義我的驗證,因爲我想,有這個想法,當我想從控制器提交,它會檢查這個組件是否驗證'checkEmail()'和'checkIsNotUsed()'。爲此,我需要控制器和內部指令p.e.之間的雙向通信。使用電子郵件:

  1. 控制器想驗證組件,所以它會調用內部指令來獲取內部輸入元素。
  2. 指令將輸入返回給控制器。
  3. 控制器可以根據鏈接到他的驗證檢查輸入。

我嘗試過不同的方法,但我無法獲得最終目標。

Here is the example I've been working with

編輯

解決:http://plnkr.co/edit/DMUVLifuWeGEuXOVfRwE?p=preview

回答

1

我會稍有懷疑你是否需要該指令作爲一個完整的黑盒子。首先,通常您需要一些驗證消息或一些向用戶顯示的有關無效數據的不同情況的信息,因此僅僅驗證者的真/假返回值是不夠的。其次,你還重新創建的很多事情已經角讓你與ngFormngModelngModelControllerinput指令,特別是ngModelController

$setValidity功能我會把每個校驗器在其自己的指令,require小號ngModel:一個用於電子郵件,另一個用於密碼。儘管如此,您仍然可以從整體控制器傳遞選項,但每個指令都是根據所需信息量身定製的。例如,validationEmail指令可以接受使用的現有的郵件的數組:

<input validation-email validation-email-used="usedEmails" ng-model="data.email" type="text" placeholder="Email" name="email" ng-required /> 

哪裏usedEmails是電子郵件的陣列。該指令可以寫成:

app.directive('validationEmail', function() { 
    return { 
    require: 'ngModel', 
    scope: { 
     validationEmailUsed:'=' 
    }, 
    link: function(scope, element, attributes, ngModelController) { 
     scope.$watch(function() { 
     return ngModelController.$viewValue 
     }, function(email) { 
     // Test the email and call 
     // ngModelController.$setValidity(...) 
     // to set the validity of the email 
     }); 
    } 
    }; 
}); 

您可以在modified version of your Plunker

編輯看到這個動作:如果要與服務器端驗證,一旦所有客戶端驗證已經從通過整合指令,可以從傳遞給ngSubmit表單上功能做到這一點:

<form name="myForm" ng-submit="submit()"> 

可使用的形式將自己暴露於範圍的事實進行編碼時,其所有ngModel控制器(用於相同的例如,使用$timeout,而不是調用$http或服務),

$scope.submit = function() { 
$timeout(function() { 
    $scope.myForm.username.$setValidity('available',false); 
    $scope.myForm.email.$setValidity('emailFree',false); 
    },500); 
} 

與這樣的一個問題是,你再會要標記的輸入爲有效用戶改變後。您可以創建一個validOnChange指令,將用作:

<input ng-model="data.username" type="text" placeholder="Username" name="username" valid-on-change="available" ng-required /> 

,並編寫了如:

app.directive('validOnChange', function() { 
    return { 
    require: 'ngModel', 
    scope: '', 
    link: function(scope, element, attributes, ngModelController) { 
     scope.$watch(function() { 
     return ngModelController.$viewValue 
     }, function() { 
     ngModelController.$setValidity(attributes.validOnChange,true); 
     }); 
    } 
    } 
}); 

你可以see this in this Plunker

使用ngForm和ngModelController的另一個一般好處是,它根據輸入的錯誤/有效狀態向窗體和元素添加了很多類,並在範圍中顯示錯誤狀態,所以您可以例如,使用ngIf可輕鬆顯示/隱藏錯誤消息。

+0

這很好,但我仍然覺得我不想驗證,直到我點擊提交。就可伸縮性而言,這種方法還不夠好,想象一下,如果字段是有效的,我希望明天檢查我的後端,我不想每次輸入時都要驗證,但當我點擊提交時。所以我的問題是,在Angular中,點擊提交時可能觸發該操作? – DreaMTT

+0

此外,使用您的解決方案,我不能使用指令來自定義輸入,我將需要。我試着編輯你的plunkr,使用嵌套的指令,但不知何故,我無法與驗證內部輸入溝通。如果你可以檢查一下,並擺脫一些ligth,我會很感激它:http://plnkr.co/edit/DB0a3rjaRhKk7NV4dt5v?p =預覽非常感謝您的幫助! – DreaMTT

+0

@DreaMTT我已經修改了我的答案,顯示瞭如何在表單通過客戶端驗證並從指令中提交給服務器之後仍然可以設置有效性。 –