Смотреть несколько переменных с полным именем неизвестно

0

У меня есть угловой контроллер:

function SignUpController($window, accountService) {

  var vm = this;
  vm.errors = null;
  vm.user = null;

  vm.submit = function (user) {

    accountService.signup(user)

      .then(function (response) {     
        $window.location.href = "/";
      })

    .catch(function (response) {
      vm.errors = response.data.errors;
    }

  };

}

API возвращает список ошибок, если они существуют, следующим образом:

[
  {code: "name", "message": "the name is required"}
]

Когда есть ошибки, я добавляю этот список в vm.errors. В HTML у меня есть:

<form name="form" ng-controller="SignUpController as vmsignup" ng-submit="vmsignup.submit(vmsignup.user)">
  <input ng-model="vmsignup.user.email" name="vmsignup.user.email" type="text" />
  <span class="error" validator="vmsignup.user.email"></span>
  <!-- Other form fields -->
</form>

Директива просматривает vm.errors и заполняет все интервалы с помощью валидаторов с правильным сообщением об ошибке.

В моих контроллерах я всегда использую vm.errors, но в своем html я часто использую что-то еще, например vmsignup, поскольку у меня может быть несколько контроллеров.

Поэтому в этом примере директива должна иметь vmsignup.errors, чтобы она работала:

angular.module("app").directive("validator", validator);
validator.$inject = ["$parse"];

function validator($parse) {

  var validator = {
    link: link,
    replace: false,
    restrict: "A"
  };

  return validator;

  function link(scope, element, attributes) {

  scope.$watch("vmsignup.errors", function (errors) {

    if (errors) {

      var result = errors.filter(function (error) {

        if (error.code == null) 
          return false;

        var position = attributes.validator.lastIndexOf(".");

        if (position > -1)
          return attributes.validator.slice(position + 1).toLowerCase() === error.code.toLowerCase();
        else
          return attributes.validator.toLowerCase() === error.code.toLowerCase();

      });          

      if (result.length > 0) {
        element.show().text(result[0].message);
        return;
      }

    }

    element.hide();

  });
}

Я бы хотел, чтобы директива имела что-то вроде:

scope.$watch("vm*.errors", ...

Полагаю, это невозможно, но должен быть способ решить это, нет?

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

<form name="form" ng-controller="SignUpController as vmsignup" validation-model="vmsignup">

Тогда я буду использовать это в директиве validator:

scope.$watch(validator.model + ".errors", function (errors) {

Это хороший вариант? Это можно сделать? Кто-нибудь может мне помочь?

  • 0
    Вы должны лучше описать проблему, которую хотите решить. Может быть, показывает больше кода .. Я чувствую, что вы можете выбрать другое решение для достижения того же результата.
  • 0
    @manzapanza Справедливо достаточно. Я просто обновил свой вопрос большим количеством кода и объяснил, что я делаю, и что такое «маленькая» проблема, которую я хотел бы решить. Помогает ли дополнительный код и информация? Я ничего не пропустил.
Теги:

3 ответа

0

Пожалуйста, попробуйте подход ниже.

      var app = angular.module('MyApp',[]);

  app.controller('MyCtrl',function($scope){
    $scope.errors =1;
    $scope.change = function(){
      $scope.errors = 2;
   }

});

  app.directive('myDirecitive',function(){

     return {
       restrict:'A',
       link:linkFunction
    }

    function linkFunction(scope,element,atrrs){            

       scope.$watch(atrrs.varName,function(newval,oldval){
         console.log("watcher called");
      });
    }

 });

  <body ng-app="MyApp", ng-controller="MyCtrl">  
   <h1>Sample Application</h1>
   <input type="text" my-direcitive var-name="errors"/>     
   <button ng-click="change()">Watch</button>     
  </body>
  • 0
    Моя идея заключалась в том, чтобы иметь в форме метки директиву validation-errors = "errors" вместо того, чтобы иметь ее во всех входных данных, поскольку она одинакова во всех них ...
  • 0
    Ага. Это похоже на ваше. Я проверил это, и это работает. Способ доступа к переменной внутри директивы немного отличается.
0

Вы не можете использовать * качестве подстановочного знака в выражении $watch, но вы можете посмотреть, например, коллекцию с $watchCollection...

Массив свойств:

$scope.$watchCollection('[prop1, prop2]', function(newValues, oldValues){
  var newProp1 = newValues[0];
  var newProp2 = newValues[1];
});

Массив функций, возвращающих значение:

$scope.$watchCollection([
    function(){
        return prop1;
    }, function(){
        return prop2;
    }
], function(newValues, oldValues){
  var newProp1 = newValues[0];
  var newProp2 = newValues[1];
});

ОБНОВИТЬ

как сказал @Ambegodas, вы можете передать коллекцию errors качестве параметра в свою директиву. Таким образом, ваш код станет:

angular
  .module("app")
  .directive("validator", validator);

validator.$inject = ["$parse"];

function validator($parse) {

  var validator = {
    link: link,
    replace: false,
    restrict: "A"
  };

  return validator;

  function link(scope, element, attributes) {

    scope.$watch(attributes.errors, function (errors) {

      if (errors) {

        var result = errors.filter(function (error) {
          if (error.code == null) return false;
          var position = attributes.validator.lastIndexOf(".");
          if (position > -1) {
            return attributes.validator.slice(position + 1).toLowerCase() === error.code.toLowerCase();
          }
          return attributes.validator.toLowerCase() === error.code.toLowerCase();
        });

        if (result.length > 0) {
          element.show().text(result[0].message);
          return;
        }
      }

      element.hide();

    }, true); // << objectEquality == true

  }
}

РАЗЛИЧНЫЙ ПРЕДЛАГАЕМЫЙ ПОДХОД

Вы можете создавать проверки на стороне сервера для тех входных данных, которые нельзя проверить только при проверке на стороне клиента.

HTML:

<form name="form" novalidate ng-submit="vm.submit(vm.account)">

  <div class="form-group" mt-show-errors>
    <label class="control-label" for="username">Username</label>
    <input type="text" mt-validate-username class="form-control" name="username" id="username" ng-model="vm.account.username" required>
    <div ng-show="form.$submitted || form.username.$touched">
      <span ng-show="form.login.$error.required" class="help-block">Username is required</span>
      <span ng-show="form.login.$error.mtValidateUsername" class="help-block">Username already taken</span>
    </div>
  </div>

  <!-- more inputs -->

</form>

ДИРЕКТИВА:

  angular
    .module('app.directives')
    .directive('mtValidateUsername', mtValidateUsername);

  function mtValidateUsername($timeout, MyAccountService) {
    return {
      require: 'ngModel',
      scope: false,
      link: function (scope, element, attrs, modelCtrl) {
        var timeoutId;
        modelCtrl.$parsers.push(function (inputValue) {
          if (!inputValue) return '';
          $timeout.cancel(timeoutId);
          timeoutId = $timeout(function () {
            MyAccountService.validateUsername(inputValue).then(function () {
              modelCtrl.$setValidity('mtValidateUsername', true);
            }).catch(function(){
              modelCtrl.$setValidity('mtValidateUsername', false);
            });
          }, 1000); // 1 second throttle
          return inputValue;
        });
      }
    };
  }
  • 0
    Да, я знаю, но это не очень хорошее решение, так как мне нужно было бы иметь коллекцию всех имен моделей представлений внутри директивы ... Трудно контролировать что-то подобное. Можно ли создать директиву проверки и получить к ней доступ? Смотрите мой обновленный вопрос ... Спасибо.
  • 0
    @MiguelMoura Вы видели, что я обновил свой ответ?
0

Вы можете использовать $ watchGroup для этой цели

  • 0
    Но могу ли я использовать "vm * .errors" в группе наблюдения, где * означает что-нибудь? Помните, что vmsignup это просто пример ... У меня может быть любой vm * в моем приложении
  • 0
    Читая о whatchGroup, я не думаю, что он принимает выражения ... Значения должны быть четко определены ...
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню