Проверка формы AngularJS: изменение значения $dirty из-за изменений состояния ui.router

Мой вариант использования:

У меня есть многошаговая форма с использованием ui-router, как в plunkr ниже. Я использую ng-форму для проверки информации, предоставляемой AngularJS, такой как $valid, $dirty и т. Д.

После каждого нажатия кнопки "Следующий раздел" я отправляю данные формы на сервер, чтобы получить их, в случае, если пользователь покидает форму перед завершением.

Если пользователь отправляет первый шаг дважды, я ТОЛЬКО отправляю отредактированные данные (если значение $ dirty равно true). Всего этого нет в plunkr, я решил показать вам простую форму, но моя форма может содержать сотню полей (радио, флажок, ввод, выбор и т. Д.).

Действия по воспроизведению проблемы (plunkr):

  1. Заполните шаг 1 и перейдите к следующему разделу
  2. Проверьте радио Xbox и вернитесь к шагу 1, нажав на номер myMultiStepForm.interests.xbox.$dirty = true
  3. Вернитесь к шагу 2 myMultiStepForm.interests.xbox.$dirty = false

Почему значение $ dirty изменено на false? Я думаю, это потому, что <ng-form> снова отображается и все данные проверки сбрасываются.

Есть ли способ избежать этого? Или, может быть, что-то другое, чем <ng-form> обрабатывать проверки подмножеств полей?

Это и есть plunkr: http://plnkr.co/edit/WclqVgiBvUXlsGdSCcj0?p=preview

2 ответа

Решение

Когда вы связываете форму или любой контроллер внутри нее, она всегда начинается как $pristine, Причина в том, что модели нравятся formData.type просто имеют некоторые значения, angular не может знать, что эти значения были состоянием по умолчанию, поступающим с сервера, или результатом предыдущего взаимодействия с пользователем; они простые string или что-то без метаданных такого рода.

Чтобы достичь того, что вы хотите, вы должны вручную отслеживать $dirty состояние через переходы состояний и применить $setDirty в форме, когда это необходимо.

Вот быстрый пример, добавление контроллера на страницы шага формы, который сохраняет состояние формы при выходе (в экземпляр общей службы вы можете добавить это через resolve тоже) и восстанавливает его при строительстве. Электрический ток formPage вводится через значение параметра по умолчанию, так что один и тот же контроллер может использоваться для всех шагов.

// router:

$stateProvider.state('form.interests', {
  url: '/interests',
  controller: 'FormStepController',  
  params: { formPage: 'interests'}
  templateUrl: 'form-interests.html'
})

// state

angular.value("formDirtyState", {});

// controller

angular.controller("FormStepController", function($scope, formDirtyState, $stateParams) {
  var formPage = stateParams.formPage;

  for(var formField in $scope.myMultiStepForm[formPage]) {
    if(formDirtyState[formPage] && formDirtyState[formPage][formField])
      $scope.myMultiStepForm[formPage][formField].$setDirty()
  }
    

  $scope.$on("$destroy", function() { 
    for(var formField in $scope.myMultiStepForm[formPage])
      formDirtyState[formField] = $scope.myMultiStepForm[formPage][formField].$dirty;
  })

})

Я решил, и решение находится в ниже плункер.

Ссылаясь на это:

Примечание: целью ngForm является группирование элементов управления, но не замена тега со всеми его возможностями (например, отправка на сервер,...).

согласно угловой документации для элемента ngForm.

Также мне интересно, почему вы используете много <ng-form> элементы. Это единственно возможное решение вашей проблемы.

Plunker Modified

Обновление 1:

Объяснение для $dirty

$dirty имеет значение true, только если пользователь взаимодействовал с этим конкретным элементом в текущей области.

Если вы так специфичны с истинной / ложной проблемой

  • Предлагая вам заменить $dirty на $pristine

Обновление 2:

Почему значение неверно при повторной навигации назад

Когда вы переходите от одной формы к другой, область действия ng-формы этого конкретного элемента добавляется к родительскому контроллеру, а при повторном посещении той же ng-формы она переопределяет область существующей.

Другие вопросы по тегам