AngularJS - Validate when ng-model value not in Select options

537 views Asked by At

I have a situation where the ng-model value may sometimes not be present in the ng-options list of a Select dropdown (ID of a user that is no longer with the company saved in a record, for example). AngularJS's behavior is that it adds an empty option to the dropdown, but does not mark it as Invalid or Error, which makes it difficult to validate. I found a solution here that uses a directive to handle this situation upon loading the page. Because I get the user Id and the list using an API call, after researching I added a $watch to make sure the data was loaded before checking, but I can't seem to get it to work. Can someone help me figure out what's wrong with my code? It seems the code inside the $validators function does not get called properly or all the time. What I need is to be able to show a message when the user ID is not in the select list, but when the user selects a name from the dropdown, the message should go away.

Here's the relevant part of my code:

<div ng-app="RfiApp" ng-controller="RfiControllerRef" class="col-sm-12">
<form class="pure-form pure-form-aligned" name="frm" method="post"
      autocomplete="off">

    <div class="form-horizontal">

        <div class="form-group">
            <label class="control-label col-md-2" for="bsa_analyst_user_id">BSA Analyst</label>
            <div class="col-md-10">
                <select class="form-control" id="bsa_analyst_user_id" name="bsa_analyst_user_id" ng-model="rfi.bsa_analyst_user_id" ng-options="s.value as s.name for s in BsaAnalysts | orderBy: 'name'" valid-values="BsaAnalysts" required>
                    <option value="">--Select--</option>
                </select>{{frm.bsa_analyst_user_id.$error}} - {{frm.bsa_analyst_user_id.$invalid}} - {{rfi.bsa_analyst_user_id}}
                <div class="text-danger"
                     ng-show="frm.bsa_analyst_user_id.$invalid"
                     ng-messages="frm.bsa_analyst_user_id.$error">
                    <div ng-message="required">BSA Analyst is required</div>
                    <div ng-message="validValues">BSA Analyst in database not valid or not in BSA Unit selected</div>
                </div>
            </div>
        </div>
    </div>
</form>
</div>

.JS Code:

RfiApp.directive('validValues', function () {
    return {
        scope: {
            validValues: '=',
            model: '=ngModel'
        },
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attributes, ngModel) {
            scope.$watch('[model,validValues]', function (newVals) {
                if (newVals[0] && newVals[1]) {
                    var values = angular.isArray(scope.validValues)
                        ? scope.validValues
                        : Object.keys(scope.validValues);
                    ngModel.$$runValidators(newVals[0], values, function () { });
                    ngModel.$validators.validValues = function (modelValue) {
                        var result = values.filter(function (obj) {
                            return obj.value == modelValue;
                        });
                        var ret = result.length > 0;
                        return ret;
                    }
                }
            });
        }
    }
});


$scope.GetDropdownValues = function () {
    var a = 1;
    DropdownOptions.get(
        function (response) {
    //... other code ommitted
            $scope.UserAnalysts = response.UserAnalystsList;
        },
        function () {
            showMessage('error', "Error");
        }
    );
};


$scope.GetExistingRfi = function () {
    NewRfiResource.get({ rfiId: $scope.rfiId },
        function (response) {
            $scope.rfi = response.rfi;
            $scope.ButtonText = "Save";
        },
        function (response) {
            showMessage('error', response.data.Message);
            $scope.GetNewRfi();
        }
    );
};

$scope.GetDropdownValues();
if ($scope.rfiId != "0") {
    $scope.GetExistingRfi();
}
else {
    $scope.GetNewRfi();
}

Thanks!

0

There are 0 answers