Пользовательский валидатор Angular приводит к тому, что переменная области видимости не определена?

Я реализую собственный валидатор для директивы, которая проверяет длину массива, но у меня возникает интересная проблема, когда я пытаюсь раскомментировать одну из строк кода в моем валидаторе:

angular.module("directives.tags", []).directive("tags", ["Tag", "$timeout", function(Tag, $timeout) {
    return {
        require: 'ngModel',
        restrict: 'E',
        scope: {
            availableTags: '=',
            currentTags: '=ngModel'
        },
        link: function($scope, element, attributes, ctrl) {

            // Snip

            $scope.updateSuggestionList = function() {
                var search = new RegExp($scope.tagInput, "i");

                $scope.suggestions = $scope.availableTags.filter(function(availableTag) {
                    if ($scope.currentTags.filter(function(currentTag) {
                            return availableTag.name == currentTag.name;
                        }).length == 0) {
                        return search.test(availableTag.name);
                    }
                    return false;
                }).slice(0,6);
            };

            // PROBLEM APPEARS TO BE HERE
            ctrl.$validators.taglength = function(currentTags) {
                return true; // <-- This works just fine
                return currentTags.length > 0 && currentTags.length < 6; // <-- This does not work at all
            };

            $scope.$watch('currentTags', function() {
                ctrl.$validate();
            }, true);

        },
        templateUrl: // snip
    }
}]);

Когда я пытаюсь использовать эту строку: return currentTags.length > 0 && currentTags.length < 6;, когда currentTags.length должен быть равен 0, он возвращает undefined:

Error: $scope.currentTags is undefined
.link/$scope.updateSuggestionList/$scope.suggestions<@http://localhost:3000/js/app.js:1116:1
.link/$scope.updateSuggestionList@http://localhost:3000/js/app.js:1115:38
anonymous/fn@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js line 13231 > Function:2:248
ngEventHandler/</callback@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js:23411:17
$RootScopeProvider/this.$get</Scope.prototype.$eval@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js:15916:16
$RootScopeProvider/this.$get</Scope.prototype.$apply@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js:16016:20
ngEventHandler/<@https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js:23416:17
n.event.dispatch@https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js:3:6414
n.event.add/r.handle@https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js:3:3224

Тем не менее, если я прокомментирую эту строку и просто верну истину или ложь. Он работает отлично, хотя и без надлежащей проверки.

Вот мой шаблон директивы:

<div class="tagger-container">
    <div class="wrapper" ng-class="{ 'active': areSuggestionsVisible }">
        <div class="tag-wrapper">
            <div class="tag" ng-repeat="tag in currentTags">
                [[ tag.name ]]
                <span class="remove" ng-click="removeTag(tag)"></span>
            </div>
        </div>
        <input type="text" class="tag-input"
               ng-model="tagInput"
               ng-style="{ width: inputLength + 'px'}"
               ng-keydown="tagInputKeydown($event)"
               ng-keyup="updateSuggestionList()"
               ng-focus="toggleSuggestionVisibility()"
               ng-blur="toggleSuggestionVisibility()" />
    </div>
    <div class="suggestions" ng-show="areSuggestionsVisible">
        <div class="suggestion" ng-repeat="tag in suggestions" ng-mousedown="createTag(tag.name)">[[ tag.name ]] </div>
    </div>
</div>

А вот как называется моя директива:

<tags available-tags="data.tags" name="tags" ng-model="text.tags"></tags>

data.tags пример:

[{ name: 'aTag', description: null, id: 1}, ..., ...]

person ReactingToAngularVues    schedule 06.09.2015    source источник
comment
Вам не нужно привязывать область действия к атрибуту ng-model (на самом деле вы не должны), так как вы require: "ngModel" - для доступа к значению используйте ctrl.$modelValue (и это может быть undefined в первом цикле дайджеста)   -  person New Dev    schedule 06.09.2015
comment
когда вызывается updateSuggestionList и как обновляются currentTags?   -  person Preethi    schedule 06.09.2015
comment
вылетает ошибка updateSuggestionList. Не мог понять, как на это влияют валидаторы! Пожалуйста, опубликуйте также код, который запускает функцию updateSuggestionList.   -  person Preethi    schedule 06.09.2015
comment
Preethi добавила шаблон директивы.   -  person ReactingToAngularVues    schedule 06.09.2015
comment
@NewDev, поэтому я попытался использовать ctrl.$modelValue и получил тот же результат - он пуст, а затем почти мгновенно не определен. Можете ли вы сказать мне, почему бы не привязать область действия к ng-model?   -  person ReactingToAngularVues    schedule 06.09.2015
comment
@EchoLogic, вы также можете опубликовать данные, передаваемые для available-tags и ng-model, в директиву tags, и будет лучше, если вы опубликуете полный код директивы.   -  person Preethi    schedule 06.09.2015
comment
Простые массивы объектов. Делайте из них все, что хотите.   -  person ReactingToAngularVues    schedule 06.09.2015


Ответы (1)


Решено. В документации для $validate():

Запускает каждый из зарегистрированных валидаторов (сначала синхронные валидаторы, а затем асинхронные валидаторы). Если действительность изменится на недопустимую, для модели будет установлено значение undefined, если только ngModelOptions.allowInvalid не имеет значение true.

Поэтому мне просто нужно установить ngModelOptions.allowInvalid = true;.

person ReactingToAngularVues    schedule 06.09.2015