Technology, Continued...

Ramblings about business, technology, development and my life

Angular, Select Inputs and 0 Values With a Required Attribute

Have you ever had a situation where you were binding your select input to a set of objects like this:

[{ value: 0, key: ‘please choose’}, { value: 1, key: ‘texas’}, {value: 2, key: ‘georgia’}]

I ran into a situation where a service that was giving me the options for the select input was setting the value for the ‘Please choose’ option to 0 instead of to blank.  This meant that if this select input was required via a “required” or “ng-required” attribute, the “please choose” would cause the browser and angular to consider the field as having a valid selection.

I had two options: change the data itself so that it was set to null or blank instead of 0, or… I thought I might create a directive to handle this.  So I created the directive.  As you can see below, this is a simple directive I threw together to consider the select to be invalid if it’s required and the value of the option selected is 0.  Not complicated, but so far it’s worked great.  The nice thing is that it’s not meant to replace the required attribute, so you can leave it or the ng-required directive, and if you’re using the ng-required directive, setting it to an expression still works fine. 

Enjoy.

/* 
Directive: required-zero-doesnt-count
JW - 2014-11-16

There are some instances where a select input has an option with a value of 0, where 0 is considered to be a placeholder option.  In other words, if the select is required, 0 doesn't count as fulfilling the 
required validation.  However, just putting the "required" attribute on the select doesn't work, because while we know the business doesn't consider "0" a valid selection, the browser thinks it is.
This directive sets required validation to false if the 0 option is selected.  

Note that this is not in place of the required attribute, but is used alongside.  The required or ng-required is still needed, or else this directive will not check for a 0 selection.
*/

(function () {
    'use strict';

    var app = angular.module('app');

    app.directive('requiredZeroDoesntCount', [function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, ngModel) {
                scope.$watch(function () {
                    //just returning a string that will be different if either view value has changed or required attribute has changed
                     return ngModel.$viewValue + "___" + attrs.required;
                }, function () {
                    if (attrs.required)
                        ngModel.$setValidity('required', ngModel.$viewValue && ngModel.$viewValue != "0");
                    else {
                        ngModel.$setValidity('required', true);
                    }
                });
            }
        };
    }]);
})();
Loading