Область обслуживания Angularjs привязки

#javascript #angularjs #angularjs-scope #angularjs-ng-repeat #angularjs-service

#javascript #angularjs #angularjs-область действия #angularjs-ng-repeat #angularjs-service

Вопрос:

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

У меня есть служба, которая вызывает две функции, которые извлекают метаданные для заполнения переменных области.

Проблема в том, что использование службы для обратного вызова данных мешает другим действиям, происходящим в коде. У меня есть директива для тега, которая показывает / скрывает ошибку в элементе span после проверки правила. Теперь это работает некорректно. Я запускаю код без асинхронных функций, тогда все работает правильно.

Мой код Plunker находится здесь

и плунжер желаемого поведения находится здесь

Рабочий пример Plunker без динамической загрузки данных

          <form class="form-horizontal">
            <div class="control-group" ng-repeat="field in viewModel.Fields">
                <label class="control-label">{{field.label}}</label>
                <div class="controls">
                    <input type="text" id="{{field.Name}}" ng-model="field.data" validator="viewModel.validator"  ruleSetName="{{field.ruleSet}}"/>
                    <span validation-Message-For="{{field.Name}}"></span>
                </div>
            </div>

            <button ng-click="save()">Submit</button>
        </form>
  

Как мне обновить все привязки, чтобы все было синхронизировано и загружено правильно?

        angular.module('dataApp', ['servicesModule', 'directivesModule'])
   .controller('dataCtrl', ['$scope', 'ProcessService', 'ValidationRuleFactory',    'Validator',
function($scope, ValidationRuleFactory, Validator, ProcessService) {

  $scope.viewModel = {};
  var FormFields = {};

  // we would get this from the meta api

  ProcessService.getProcessMetaData().then(function(data) {

    alert("here");

    FormFields = {
      Name: "Course",
      Fields: [{
        type: "text",
        Name: "name",
        label: "Name",
        data: "",
        required: true,
        ruleSet: "personFirstNameRules"
      }, {
        type: "text",
        Name: "description",
        label: "Description",
        data: "",
        required: true,
        ruleSet: "personEmailRules"
      }]
    };


    $scope.viewModel.Fields = FormFields;


    ProcessService.getProcessRuleData().then(function(data) {

      var genericErrorMessages = {
        required: 'Required',
        minlength: 'value length must be at least %s characters',
        maxlength: 'value length must be less than %s characters'
      };
      var rules = new ValidationRuleFactory(genericErrorMessages);

      $scope.viewModel.validationRules = {
        personFirstNameRules: [rules.isRequired(), rules.minLength(3)],
        personEmailRules: [rules.isRequired(), rules.minLength(3), rules.maxLength(7)]
      };



      $scope.viewModel.validator = new Validator($scope.viewModel.validationRules);

    });

  });

  var getRuleSetValuesMap = function() {
    return {
      personFirstNameRules: $scope.viewModel.Fields[0].data,
      personEmailRules: $scope.viewModel.Fields[1].data
    };
  };

  $scope.save = function() {
    $scope.viewModel.validator.validateAllRules(getRuleSetValuesMap());
    if ($scope.viewModel.validator.hasErrors()) {
      $scope.viewModel.validator.triggerValidationChanged();
      return;
    } else {
      alert('person saved in!');
    }
  };

}
]);
  

Директива о сообщении проверки находится здесь

 (function(angular, $) {

angular.module('directivesModule')
        .directive('validationMessageFor', [function() {
                return {
                    restrict: 'A',
                    scope: {eID: '@val'},
                    link: function(scope, element, attributes) {

                        //var errorElementId = attributes.validationMessageFor;

                        attributes.$observe('validationMessageFor', function(value) {

                            errorElementId = value;

                            //alert("called");

                            if (!errorElementId) {
                                return;
                            }
                            var areCustomErrorsWatched = false;

                            var watchRuleChange = function(validationInfo, rule) {
                                scope.$watch(function() {
                                    return validationInfo.validator.ruleSetHasErrors(validationInfo.ruleSetName, rule.errorCode);
                                }, showErrorInfoIfNeeded);
                            };
                            var watchCustomErrors = function(validationInfo) {
                                if (!areCustomErrorsWatched amp;amp; validationInfo amp;amp; validationInfo.validator) {
                                    areCustomErrorsWatched = true;
                                    var validator = validationInfo.validator;
                                    var rules = validator.validationRules[validationInfo.ruleSetName];
                                    for (var i = 0; i < rules.length; i  ) {
                                        watchRuleChange(validationInfo, rules[i]);
                                    }
                                }
                            };

                            // get element for which we are showing error information by id
                            var errorElement = $("#"   errorElementId);
                            var errorElementController = angular.element(errorElement).controller('ngModel');
                            var validatorsController = angular.element(errorElement).controller('validator');

                            var getValidationInfo = function() {
                                return validatorsController amp;amp; validatorsController.validationInfoIsDefined() ? validatorsController.validationInfo : null;
                            };

                            var validationChanged = false;
                            var subscribeToValidationChanged = function() {
                                if (validatorsController.validationInfoIsDefined()) {
                                    validatorsController.validationInfo.validator.watchValidationChanged(function() {
                                        validationChanged = true;
                                        showErrorInfoIfNeeded();
                                    });

                                    // setup a watch on rule errors if it's not already set
                                    watchCustomErrors(validatorsController.validationInfo);
                                }
                            };

                            var getErrorMessage = function(value) {
                                var validationInfo = getValidationInfo();
                                if (!validationInfo) {
                                    return '';
                                }

                                var errorMessage = "";
                                var errors = validationInfo.validator.errors[validationInfo.ruleSetName];
                                var rules = validationInfo.validator.validationRules[validationInfo.ruleSetName];

                                for (var errorCode in errors) {
                                    if (errors[errorCode]) {
                                        var errorCodeRule = _.findWhere(rules, {errorCode: errorCode});
                                        if (errorCodeRule) {
                                            errorMessage  = errorCodeRule.validate(value).errorMessage;
                                            break;
                                        }
                                    }
                                }

                                return errorMessage;
                            };

                            var showErrorInfoIfNeeded = function() {
                                var validationInfo = getValidationInfo();
                                if (!validationInfo) {
                                    return;
                                }

                                var needsAttention = validatorsController.ruleSetHasErrors() amp;amp; (errorElementController amp;amp; errorElementController.$dirty || validationChanged);
                                if (needsAttention) {
                                    // compose and show error message
                                    var errorMessage = getErrorMessage(element.val());

                                    // set and show error message
                                    element.text(errorMessage);
                                    element.show();
                                } else {
                                    element.hide();
                                }
                            };

                            subscribeToValidationChanged();
                            if (errorElementController)
                            {
                                scope.$watch(function() {
                                    return errorElementController.$dirty;
                                }, showErrorInfoIfNeeded);
                            }
                            scope.$watch(function() {
                                return validatorsController.validationInfoIsDefined();
                            }, subscribeToValidationChanged());
                        });
                    }
                };
            }]);
    })(angular, $);
  

Комментарии:

1. Пожалуйста, укажите, в чем именно проблема.

2. @TommyK Да, проблема неясна… Но похоже, что решение может быть таким же простым, как перемещение $scope.viewModel.validator = new Validator($scope.viewModel.validationRules); внутри функции обратного вызова (т. Е. После $scope.viewModel.validationRules = data; ).

3. Спасибо. Надеюсь, я немного прояснил проблему.