Edit in JSFiddle

//Inspired by http://stackoverflow.com/questions/16202254/ng-options-with-disabled-rows/20790905#20790905
//Written by David Votrubec from ST-Software
//up-to-date code is on Github! https://github.com/ST-Software/STAngular/blob/master/src/directives/SgOptionsDisabled

//this issue should be fixed by Angular 1.4

angular.module('myApp', [])
.directive('sgOptionsDisabled', function ($parse) {
        var disableOptions = function (scope, attr, element, data, fnDisableIfTrue) {
            // refresh the disabled options in the select element.
            var containsEmptyOption = element.find("option[value='']").length != 0;
            angular.forEach(element.find("option"), function (value, index) {
                var elem = angular.element(value);
                if (elem.val() != "") {
                    var locals = {};
                    //ST-Software modification (index-1 because of the initial empty option)
                    var i = containsEmptyOption ? index - 1 : index;
                    locals[attr] = data[i];
                    elem.attr("disabled", fnDisableIfTrue(scope, locals));
                }
            });
        };
        return {
            priority: 0,
            require: 'ngModel',
            link: function (scope, iElement, iAttrs, ctrl) {
                // parse expression and build array of disabled options
                var expElements = iAttrs.sgOptionsDisabled.match(/^\s*(.+)\s+for\s+(.+)\s+in\s+(.+)?\s*/);
                var attrToWatch = expElements[3];
                var fnDisableIfTrue = $parse(expElements[1]);
                scope.$watch(attrToWatch, function (newValue, oldValue) {
                    if (newValue)
                        disableOptions(scope, expElements[2], iElement, newValue, fnDisableIfTrue);
                }, true);
                // handle model updates properly
                scope.$watch(iAttrs.ngModel, function (newValue, oldValue) {
                    var disOptions = $parse(attrToWatch)(scope);
                    if (newValue)
                        disableOptions(scope, expElements[2], iElement, disOptions, fnDisableIfTrue);
                });
            }
        };
    });

function OptionsController($scope) {
    var options = [
        {id:1, name: 'enabled option 1', disabled: false},
        {id:2, name: 'disabled option 2', disabled: true},
        {id:3, name: 'disabled option 3', disabled: true},
        {id:4, name: 'enabled option 4', disabled: false},
        {id:5, name: 'enabled option 5'},
    ];
    
    $scope.options = options;

    $scope.myOption = options[1].id;
    $scope.myOption2 = options[1].id;
}
<div ng-controller="OptionsController">
    
    <!-- Without empty option -->
    <select ng-model="myOption" 
        ng-options="o.id as o.name for o in options"
        sg-options-disabled="o.disabled == true for o in options"></select>
    
    <div ng-bind="myOption"></div> 
    
    <br/>
    <br/>
    <br/>
    
    <!-- With empty option -->
    <select ng-model="myOption2" 
        ng-options="o.id as o.name for o in options"
        sg-options-disabled="o.disabled == true for o in options">
            <option value=""></option>
        </select>
    
    <div ng-bind="myOption2"></div> 
</div>

              

External resources loaded into this fiddle: