例から取った保存ボタンを含むangularアプリがあります:
<button ng-click="save" ng-disabled="form.$invalid">SAVE</button>
ユーザーが問題を修正するとform.$invalid
がfalseになるため、これはクライアント側の検証に適していますが、別のユーザーが同じ電子メールで登録されている場合は無効に設定される電子メールフィールドがあります。
メールフィールドを無効に設定するとすぐにフォームを送信できず、ユーザーはその検証エラーを修正する方法がありません。そのため、form.$invalid
を使用して送信ボタンを無効にすることはできなくなりました。
より良い方法があるはずです
いくつかのプロジェクトでこれが必要だったので、ディレクティブを作成しました。最後に、ドロップインソリューションを必要とする人のためにGitHubに掲載するために少し時間がかかりました。
https://github.com/webadvanced/ng-remote-validate
機能:
テキストまたはパスワード入力のAjax検証のためのドロップインソリューション
Angularsビルド検証で動作し、formName.inputName。$ error.ngRemoteValidateでアクセスできます。
サーバー要求をスロットルします(デフォルトは400ミリ秒)。ng-remote-throttle="550"
で設定できます
ng-remote-method="GET"
を使用したHTTPメソッド定義(デフォルトのPOST)を許可します
ユーザーが現在のパスワードと新しいパスワードを入力する必要があるパスワード変更フォームの使用例:
<h3>Change password</h3>
<form name="changePasswordForm">
<label for="currentPassword">Current</label>
<input type="password"
name="currentPassword"
placeholder="Current password"
ng-model="password.current"
ng-remote-validate="/customer/validpassword"
required>
<span ng-show="changePasswordForm.currentPassword.$error.required && changePasswordForm.confirmPassword.$dirty">
Required
</span>
<span ng-show="changePasswordForm.currentPassword.$error.ngRemoteValidate">
Incorrect current password. Please enter your current account password.
</span>
<label for="newPassword">New</label>
<input type="password"
name="newPassword"
placeholder="New password"
ng-model="password.new"
required>
<label for="confirmPassword">Confirm</label>
<input ng-disabled=""
type="password"
name="confirmPassword"
placeholder="Confirm password"
ng-model="password.confirm"
ng-match="password.new"
required>
<span ng-show="changePasswordForm.confirmPassword.$error.match">
New and confirm do not match
</span>
<div>
<button type="submit"
ng-disabled="changePasswordForm.$invalid"
ng-click="changePassword(password.new, changePasswordForm);reset();">
Change password
</button>
</div>
</form>
これは、カスタムディレクティブが友人である別のケースです。ディレクティブを作成し、それに$ httpまたは$ resourceを挿入して、検証中にサーバーにコールバックする必要があります。
カスタムディレクティブのいくつかの擬似コード:
app.directive('uniqueEmail', function($http) {
var toId;
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elem, attr, ctrl) {
//when the scope changes, check the email.
scope.$watch(attr.ngModel, function(value) {
// if there was a previous attempt, stop it.
if(toId) clearTimeout(toId);
// start a new attempt with a delay to keep it from
// getting too "chatty".
toId = setTimeout(function(){
// call to some API that returns { isValid: true } or { isValid: false }
$http.get('/Is/My/EmailValid?email=' + value).success(function(data) {
//set the validity of the field
ctrl.$setValidity('uniqueEmail', data.isValid);
});
}, 200);
})
}
}
});
そして、マークアップで使用する方法は次のとおりです。
<input type="email" ng-model="userEmail" name="userEmail" required unique-email/>
<span ng-show="myFormName.userEmail.$error.uniqueEmail">Email is not unique.</span>
編集:上記で何が起こっているかの簡単な説明。
...つまり、ユーザーにとって:
EDIT2:これにより、form。$ invalidを使用して送信ボタンを無効にすることもできます。
私は完璧に機能するソリューションでプランカーを作成しました。カスタムディレクティブを使用しますが、単一フィールドではなくフォーム全体で使用します。
http://plnkr.co/edit/HnF90JOYaz47r8zaH5JY
サーバー検証の送信ボタンを無効にすることはお勧めしません。
OK。誰かが作業バージョンを必要とする場合、ここにあります:
ドキュメントから:
_ $apply() is used to enter Angular execution context from JavaScript
(Keep in mind that in most places (controllers, services)
$apply has already been called for you by the directive which is handling the event.)
_
これにより、私は必要がないと思いました:$scope.$apply(function(s) {
そうでなければ、_$digest
_について文句を言うでしょう
_app.directive('uniqueName', function($http) {
var toId;
return {
require: 'ngModel',
link: function(scope, elem, attr, ctrl) {
//when the scope changes, check the name.
scope.$watch(attr.ngModel, function(value) {
// if there was a previous attempt, stop it.
if(toId) clearTimeout(toId);
// start a new attempt with a delay to keep it from
// getting too "chatty".
toId = setTimeout(function(){
// call to some API that returns { isValid: true } or { isValid: false }
$http.get('/rest/isUerExist/' + value).success(function(data) {
//set the validity of the field
if (data == "true") {
ctrl.$setValidity('uniqueName', false);
} else if (data == "false") {
ctrl.$setValidity('uniqueName', true);
}
}).error(function(data, status, headers, config) {
console.log("something wrong")
});
}, 200);
})
}
}
});
_
HTML:
_<div ng-controller="UniqueFormController">
<form name="uniqueNameForm" novalidate ng-submit="submitForm()">
<label name="name"></label>
<input type="text" ng-model="name" name="name" unique-name> <!-- 'unique-name' because of the name-convention -->
<span ng-show="uniqueNameForm.name.$error.uniqueName">Name is not unique.</span>
<input type="submit">
</form>
</div>
_
コントローラーは次のようになります。
_app.controller("UniqueFormController", function($scope) {
$scope.name = "Bob"
})
_
https://github.com/webadvanced/ng-remote-validate について学んだこのページの回答に感謝します。
オプションディレクティブは、ディレクティブを記述する各フィールドとして、私があまり好きではないよりもわずかに少ないです。モジュールは同じです-ユニバーサルソリューション。
しかし、モジュールでは私は何かが欠けていました-いくつかのルールのフィールドを確認してください。
その後、モジュールを変更しました https://github.com/borodatych/ngRemoteValidate
ロシアのREADMEに対する謝罪は、最終的に変更されます。
急いで同じ問題を抱えている人を共有します。
はい、このためにここに集まりました...
負荷:
<script type="text/javascript" src="../your/path/remoteValidate.js"></script>
含める:
var app = angular.module( 'myApp', [ 'remoteValidate' ] );
[〜#〜] html [〜#〜]
<input type="text" name="login"
ng-model="user.login"
remote-validate="( '/ajax/validation/login', ['not_empty',['min_length',2],['max_length',32],'domain','unique'] )"
required
/>
<br/>
<div class="form-input-valid" ng-show="form.login.$pristine || (form.login.$dirty && rv.login.$valid)">
From 2 to 16 characters (numbers, letters and hyphens)
</div>
<span class="form-input-valid error" ng-show="form.login.$error.remoteValidate">
<span ng:bind="form.login.$message"></span>
</span>
バックエンド[Kohana]
public function action_validation(){
$field = $this->request->param('field');
$value = Arr::get($_POST,'value');
$rules = Arr::get($_POST,'rules',[]);
$aValid[$field] = $value;
$validation = Validation::factory($aValid);
foreach( $rules AS $rule ){
if( in_array($rule,['unique']) ){
/// Clients - Users Models
$validation = $validation->rule($field,$rule,[':field',':value','Clients']);
}
elseif( is_array($rule) ){ /// min_length, max_length
$validation = $validation->rule($field,$rule[0],[':value',$rule[1]]);
}
else{
$validation = $validation->rule($field,$rule);
}
}
$c = false;
try{
$c = $validation->check();
}
catch( Exception $e ){
$err = $e->getMessage();
Response::jEcho($err);
}
if( $c ){
$response = [
'isValid' => TRUE,
'message' => 'GOOD'
];
}
else{
$e = $validation->errors('validation');
$response = [
'isValid' => FALSE,
'message' => $e[$field]
];
}
Response::jEcho($response);
}