フォームの検証に使用する「show-errors」という角度ディレクティブがあります。これにより、検証が失敗したときに「has-error」CSS クラスが含まれている div に適用されます。これは、ユーザーが入力ボックスを離れたとき (ぼかし) や、ユーザーが [続行] ボタンをクリックしたとき (これは複数ステップのフォームです) など、ほとんどの場合にうまく機能します。「show-errors-check-validity」メッセージをブロードキャストすることにより、続行時にすべてのフォーム要素の検証をトリガーします。
$rootScope.$broadcast('show-errors-check-validity');
ディレクティブは次のとおりです。
angular
.module('eStoreApp')
.directive('showErrors', showErrors);
function showErrors($log, $rootScope, $timeout) {
return {
restrict: 'A',
require: '^form',
link: function(scope, el, attrs, formCtrl) {
var domElement = el[0].querySelector("[name]");
var angularElement = angular.element(domElement);
var textBoxName = angularElement.attr('name');
var d = new Date();
var time = d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds();
angularElement.bind('blur', function () {
$log.debug(time + ': BLUR: Input validation: ' + textBoxName + '. Valid = ' + !formCtrl[textBoxName].$invalid);
el.toggleClass('has-error', formCtrl[textBoxName].$invalid);
});
scope.$on('show-errors-check-validity', function() {
$log.debug(time + ': SHOW-ERRORS: Input validation: ' + textBoxName + '. Valid = ' + !formCtrl[textBoxName].$invalid);
el.toggleClass('has-error', formCtrl[textBoxName].$invalid);
});
}
};
}
HTML での使用方法は次のとおりです。
<div class="form-group row" show-errors>
<label class="col-sm-2 control-label">Zip Code</label>
<div class="col-sm-10">
<input type="text" name="zip" class="form-control" required ng-model="vm.checkoutData.data.shipping.zip">
<p class="help-block" ng-if="shippingInformationForm.zip.$error.required">Zip Code is required.</p>
</div>
</div>
これはすべて、promise の戻り値、具体的には $modal.open() で検証をトリガーしようとするまではうまく機能します。ユーザーはモーダルを開いて、フォームに入力されている以前に保存した住所を選択できます。彼らがこれを行うとき、検証をトリガーしたいと思います。ここでも、'show-errors-check-validity' メッセージを使用しています。これはディレクティブの関数にヒットしますが、angularjs フォームの $error 値はまだ更新されていません。$rootScope.$digest() を呼び出すと、ダイジェストが進行中であるというエラーが表示されます。angularjs $scope.shippingAddressForm.zip.$invalid が更新された後にディレクティブを起動するにはどうすればよいですか?
以下の selectAddress() 関数は、shippingAddressForm と「show-errors」ディレクティブを持つすべてのフォーム要素を含むセクションのコントローラにあります。
function selectAddress() {
var modalInstance = $modal.open({
templateUrl: 'Scripts/Checkout/AddressSelector/addressSelector.html',
controller: 'addressSelectorController',
controllerAs: 'vm',
size: 'sm',
resolve: {
addresses: function() {
return shippingAddressService.getAll();
}
}
});
modalInstance.result.then(function (selectedAddress) {
vm.checkoutData.data.shipping = selectedAddress;
if (selectedAddress.id) {
$scope.$emit('show-errors-check-validity');
}
}, function() {
$log.info('Modal dismissed.');
});
}