Pro AngularJS, Chapter 17, $formatters and $parsers
HTML
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script type="text/ng-template" id="triTemplate">
<div class = "well">
<div class="btn-group">
<button class = "btn btn-default">Yes</button>
<button class="btn btn-default">No</button>
<button class = "btn btn-default">Not Sure</button>
</div>
<span class="error" ng-show ="myForm.decision.$error.confidence" > You need to be sure</span>
</div>
</script>
<body ng-app="exampleApp" ng-controller="defaultCtrl">
<form name="myForm" novalidate>
<div>
<tri-button name="decision" ng-model="dataValue" />
</div>
</form>
<div class="well">Value:
<select ng-model="dataValue">
<option>Yes</option>
<option>No</option>
<option>Not Sure</option>
<option>Huh?</option>
</select>
</div>
</body>
JavaScript
var myApp = angular.module("exampleApp", []);
myApp.controller("defaultCtrl", function ($scope) {
$scope.dataValue = "Not Sure";
})
.directive("triButton", function () {
return {
restrict: "E",
replace: true,
require: "ngModel",
template: document.querySelector("#triTemplate").outerText,
link: function (scope, element, attrs, ctrl) {
var buttons = element.find("button"),
setSelected = function (value) {
buttons.removeClass("btn-primary");
for (var i = 0; i < buttons.length; i++) {
if (buttons.eq(i).text() === value) {
buttons.eq(i).addClass("btn-primary");
}
}
},
validateParser = function (value) {
var valid = (value == "Yes" || value == "No");
ctrl.$setValidity("confidence", valid);
return valid ? value : undefined;
};
ctrl.$render = function () {
var val = ctrl.$viewValue;
validateParser(val);
setSelected(val || "Not Sure");
};
ctrl.$formatters.push(function (value) {
return value == "Huh?" ? "Not Sure" : value;
});
ctrl.$parsers.push(validateParser);
buttons.on("click", function (event) {
var val = event.target.innerText;
setSelected(val);
scope.$apply(function () {
ctrl.$setViewValue(val);
});
});
}
}
});