<html>
<head>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css" />
<link rel="stylesheet" href="style.css" />
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular-messages.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="app" ng-controller="Main as ctrl" ng-cloak="">
<form class="container" name="sampleForm" novalidate="" ng-submit="ctrl.submitHandler()">
<h1>ngMessages Sample</h1>
<div class="form-group">
<section class="container" name="checkboxes" ng-model="ctrl.checkboxes" cm-check-boxes-required="">
<h2 class="title title--required">CheckBoxes (custom validator)</h2>
<div class="bg-danger" ng-messages="sampleForm.checkboxes.$error" ng-if="sampleForm.$submitted">
<p class="text-danger padding--10px" ng-message="checkBoxesRequired">1 つ以上選択してください</p>
</div>
<div class="checkbox" ng-repeat="item in ctrl.checkboxes">
<label class="checkbox-inline">
<input type="checkbox" class="checkbox-inline" ng-model="item.value" />{{item.label}}
</label>
</div>
</section>
<section class="container">
<h2 class="title title--required">TextInput (normal validator)</h2>
<div class="bg-danger" ng-messages="sampleForm.myName.$error" ng-if="sampleForm.$submitted">
<p class="text-danger padding--10px" ng-message="required">必須項目です</p>
<p class="text-danger padding--10px" ng-message="minlength">5 文字以上入力してください</p>
<p class="text-danger padding--10px" ng-message="maxlength">20 文字以上入力できません</p>
</div>
<div class="form-group">
<input type="text"
name="myName"
ng-model="name"
ng-minlength="5"
ng-maxlength="20"
ng-required="true" />
</div>
</section>
</div>
<section class="container top-buffer">
<input type="submit" class="btn btn-primary" value="CHECK" />
<button class="btn btn-default" ng-click="ctrl.resetHandler($event)">RESET</button>
</section>
</form>
</body>
</html>
(function() {
'use strict';
angular.module('app', ['ngMessages'/*'ui.bootstrap'*/], function(){
})
.config(function(/*$locationProvider, $logProvider, $httpProvider*/) {
})
.directive('cmCheckBoxesRequired', function() {
return {
'restrict' : 'A',
'require' : '?ngModel',
'link' : function(scope, elm, attr, ctrl) {
if (!ctrl) {
return;
}
var invalid = false;
var watcher;
var jqContainer = angular.element(elm);
var checkVlidatate = function() {
var result = jqContainer.find('input[type=\'checkbox\']:checked');
return !angular.equals(result.length, 0);
};
watcher = scope.$watch(attr.ngModel, function(newValue, oldValue) {
if(!newValue || !oldValue) {
return;
} else if (!angular.equals(newValue, oldValue)) {
invalid = checkVlidatate();
ctrl.$setValidity('checkBoxesRequired', invalid);
}
}, true);
ctrl.$validators.checkBoxesRequired = function(modelValue, viewValue) {
return invalid;
};
var destroy = scope.$on('$destroy', function() {
watcher();
destroy();
});
}
};
})
.controller('Main', function($scope, $log) {
$log.debug('Main');
var scope = $scope;
var ctrl = this;
ctrl.checkboxes = [
{'value' : false, 'label' : '選択肢 1' },
{'value' : false, 'label' : '選択肢 2' },
{'value' : false, 'label' : '選択肢 3' },
{'value' : false, 'label' : '選択肢 4' }
];
ctrl.submitHandler = function() {
$log.debug('ctrl.submit ', scope);
};
ctrl.resetHandler = function(event) {
event.preventDefault();
var form = scope.sampleForm;
form.$setUntouched();
form.$setPristine();
};
});
}());
.title--required:after {
content : "*";
color : red;
padding-left : 10px;
}
.padding--10px {
padding : 10px;
}