2013-11-13 3 views
0

Это надуманный пример, но один, который демонстрирует проблему, я встречая.Угловая (сфера?), что требует, чтобы родитель FormController

У меня есть форма, которая имеет вход, который генерируется с использованием директивы. Код выглядит следующим образом. скрипку здесь http://jsfiddle.net/technicolorenvy/CFynn/2/

Посмотреть

<div ng-controller="AppController"> 
     <form name="myForm"> 
      <input name="myInput" id="myInput" ng-model="myInputModel" ng-pattern="/\d+/" my-directive required/> 
      <button type="submit" ng-click="submitForm()">Submit</button> 
     </form> 
    </div> 

Контроллер

app.controller('AppController', function ($scope) { 
     $scope.submitForm = function() { 
      console.log('form controller inside AppController submitForm()'); 
      console.log(angular.copy($scope.myForm)); 
      console.log('is the form valid? ' + $scope.myForm.$valid); 
      console.log(' '); 
     }; 
    }); 

Директива

app.directive('myDirective', function() { 
     return { 
      template: '<div><input/></div>', 
      replace: true, 
      restrict: 'A', 
      require: '^form', 
      compile: function (element, attrs) { 
       // some setup here 
       // move the id and ng-model down onto the enclosed input 
       element.removeAttr('id').removeAttr('ng-model').removeAttr('name'); 
       element.find('input').attr('id', attrs.id).attr('ng-model', attrs.ngModel).attr('name', attrs.name); 

       var inputName = attrs.name, 
        $input = element.find('input'); 
       if (attrs.required) { 
        element.removeAttr('required'); 
        $input.attr('required', true); 
       } 
       if (attrs.ngPattern) { 
        element.removeAttr('ng-pattern'); 
        $input.attr('ng-pattern', attrs.ngPattern); 
       } 

       return { 
        pre: function (scope, element, attrs, formCtrl) { 
         var patternErrs, 
         fakeNum = 1234; 

         $input.on('change', function() { 
          patternErrs = formCtrl.$error.pattern; 
          if (patternErrs && patternErrs.length > 0) { 
           angular.forEach(patternErrs, function (err) { 
            if (err.$name === inputName) { 
             $input.val(fakeNum); 
             formCtrl[inputName].$setViewValue(fakeNum); 
             formCtrl[inputName].$setValidity('pattern', true); 
            } 
           }); 
          } 
          console.log('formCtrl inside directive'); 
          console.log(angular.copy(formCtrl)); 
          console.log('is the form valid? ' + formCtrl.$valid); 
          console.log(' '); 
         }); 
        } 
       }; 
      } 
     } 
    }); 

В директиве у меня есть событие OnChange на 'генерируемой' вход, который проверяет наличие шаблона ошибки, соответствующие имени этого ввода, тогда, если есть, сила данные должны быть то, что нам нужно с поддельным значением, с использованием setViewValue, а затем установить срок действия с использованием setValidity.

Это работает ... вроде. Проблема заключается в том, что в FIRST submit форма всегда недействительна. Вы должны нажать кнопку Отправить TWICE, чтобы форма считалась действительной. (Шаги включены ниже)

  1. Введите строку (например, «ABCD») на входе
  2. вход не проходит проверку шаблона, а затем получает действительное значение (1234)
  3. директиву «myDirective» обрабатывает этот + устанавливает значение входного и валидность в
  4. на ПЕРВОМ заполните, однако, форма является недействительной
  5. на втором представить без изменения ввода, форма действует

Итак, как я могу сделать форму действительной при первом отправке? БЕЗ симулирования действительности формы (читайте, я не хочу, чтобы вручную была установлена ​​форма, чтобы она была действительной). Это похоже на проблему, но если да, я не слишком уверен, как ее исправить.

Спасибо!

ответ

2

Вам необходимо позвонить scope.$apply() в свое событие изменения после того, как вы закончите изменять область действия.

Это сказано .. Я не уверен, что вы пытаетесь сделать здесь.

Похоже, что вы можете попытаться решить простую проблему сложным способом. Очевидно, что код не очень проверен. Возможно, что-то из того, что делается, на самом деле является «бизнес-логикой», которая может быть инкапсулирована в контроллер?

Какова точная цель здесь?

+0

Опять же, супер надуманный пример. реальный случай это. У меня есть директива, которая будет создавать входы, которые используют директиву bs-datepicker. улов по умолчанию, bs-datepicker приходит в несколько горячий и обновит атрибут value элемента до текущего дня, если введен неверный текст. После этого bs-datepicker добавит коллекцию дат в formController. $ Error и input. $ Errors collections. Но интерфейс плох. Поскольку он _looks_, как будто у вас есть действительный ввод. Мое намерение заключалось в том, чтобы использовать пользовательский интерфейс «default», предоставляемый bs-datepicker, но на самом деле массировать его таким образом, чтобы он был действительным – technicolorenvy

+0

, основываясь на вышесказанном, является ли это еще более важным способом сделать это? – technicolorenvy

+0

Хм, это сложно ... Вам может быть лучше изменить директиву bsdatepicker в соответствии с вашими потребностями. Это может быть так же просто, как изменение его приоритета или, возможно, переупорядочение функций проверки в nsModel $ parsers и $ formatters. Моя кишка говорит мне, что в любое время, когда у вас есть директива, просто перетасовывая атрибуты и обманывая другую директиву, вы можете * лаять на неправильное дерево. В конце концов, все, что работает, лучше. Однако что бы ни было * проверяемым * и работает * еще лучше *. –

1

Этот код внутри вашего $ input.on ('change') никогда не переваривается ... то есть, Angular никогда не знала, чтобы запускать все свои часы и внутренние процедуры после вашего события изменения. Таким образом, он запускает его во время первого дайджеста, что происходит при первом запуске Submit.

Я думаю, что если вы завернули этот бит в $ timeout() или использовали $ scope. $ Apply(), это решило проблему.

+0

Угловой не «переваривает код».Когда возникает дайджест $, область рассматривается для изменений и увольняются $ watch handlers. Эта функция в '$ input.on ('change', HERE)' является просто обработчиком события DOM. –

+0

поочередно мог использовать 'ng-change', который угловой будет смотреть – charlietfl

Смежные вопросы