2013-06-13 2 views
16

У меня есть форма ng на странице. Внутри формы у меня есть несколько элементов управления, которые должны отображать диалог сохранения, когда форма грязная, т.е. форма. $ Dirty = true. Однако есть некоторые элементы управления навигацией в том виде, в котором я не хочу загрязнять форму. Предположим, я не могу вывести элемент управления из формы.

см: http://plnkr.co/edit/bfig4B

Как сделать выбор коробки не грязная форма?

ответ

7

Угловая только устанавливает форму грязной, если элемент управления является нетронутым. Итак, трюк здесь заключается в том, чтобы установить $ pristine на элемент управления на false. Вы можете сделать это в тайм-ауте в контроллере.

см: http://plnkr.co/edit/by3qTM

+0

Большое вам спасибо! – cheeesus

+0

Когда я нажимаю пробел в текстовом поле, форма не становится грязной, – Developer

24

Вот вариант ответа @ Акация, используя директиву и не используя $ таймаут. Это упростит ваши контроллеры.

.directive('noDirtyCheck', function() { 
    // Interacting with input elements having this directive won't cause the 
    // form to be marked dirty. 
    return { 
    restrict: 'A', 
    require: 'ngModel', 
    link: function(scope, elm, attrs, ctrl) { 
     ctrl.$pristine = false; 
    } 
    } 
}); 

Затем используйте его в форме, как так:

<input type="text" name="foo" ng-model="x.foo" no-dirty-check> 
+1

Это отличная реализация, но она страдает от проблемы @dmitankin, указанной в форме. $ SetPristine(). –

12

Установка первозданного свойства $ ложь, только при инициализации, работает до вызова $ setPristine() в форме. Тогда ваш элемент управления имеет свое первоначальное значение true, и изменение значения ввода сделает вашу форму грязной. Чтобы избежать этого, установите $ нетронутый на фокусе:

link: function(scope, elm, attrs, ctrl) { 
    elm.focus(function() { 
     ctrl.$pristine = false; 
    }); 
} 
12

я использовал решение @ overthink, но столкнулся с проблемой, упомянутой @dmitankin. Однако я не хотел прикреплять обработчик к событию фокуса. Поэтому вместо этого я попытался переопределить $ первозданное свойство и заставить его всегда возвращать false. Я закончил использование Object.defineProperty, который не поддерживается в IE8 и ниже. Есть workarounds сделать это в тех старых браузерах, но я им не нужны, поэтому они не являются частью моего решения ниже:

(function() { 
    angular 
     .module("myapp") 
     .directive("noDirtyCheck", noDirtyCheck); 

    function noDirtyCheck() { 
     return { 
      restrict: 'A', 
      require: 'ngModel', 
      link: function (scope, elem, attrs, ctrl) { 
       var alwaysFalse = { 
        get: function() { return false; }, 
        set: function() { } 
       }; 
       Object.defineProperty(ctrl, '$pristine', alwaysFalse); 
       Object.defineProperty(ctrl, '$dirty', alwaysFalse); 
      } 
     }; 
    } 
})(); 

Я также переопределяя $ загрязнен, поэтому он не может быть установлен как грязный тоже.

+0

Единственное решение, которое надежно работало при использовании 'form. $ SetPristine()' в какой-то момент. –

0

я столкнулся с некоторыми проблемами с этой реализацией, так вот мой (более сложный):

app.directive('noDirtyCheck', [function() { 
 
     // Interacting with input elements having this directive won't cause the 
 
     // form to be marked dirty. 
 
     // http://stackoverflow.com/questions/17089090/prevent-input-from-setting-form-dirty-angularjs 
 
     return { 
 
      restrict: 'A',   
 
      require: ['^form', '^ngModel'], 
 

 
      link: function (scope, element, attrs, controllers) { 
 
       var form = controllers[0]; 
 
       
 
       var currentControl = controllers[1]; 
 

 
       var formDirtyState = false; 
 

 
       var manualFocus = false; 
 

 
       element.bind('focus',function() { 
 
        manualFocus = true; 
 
        if (form) {       
 
         window.console && console.log('Saving current form ' + form.$name + ' dirty status: ' + form.$dirty); 
 
         formDirtyState = form.$dirty; // save form's dirty state 
 
        } 
 
       }); 
 
       
 
       element.bind('blur', function() { 
 
        if (currentControl) { 
 
         window.console && console.log('Resetting current control (' + currentControl.$name + ') dirty status to false (called from blur)'); 
 
         currentControl.$dirty = false; // Remove dirty state but keep the value 
 
         if (!formDirtyState && form && manualFocus) { 
 
          window.console && console.log('Resetting ' + form.$name + ' form pristine state...'); 
 
          form.$setPristine(); 
 
         } 
 
         manualFocus = false; 
 
         //   scope.$apply(); 
 
        } 
 
       }); 
 
      } 
 
     }; 
 
    }]);

+1

У кого были проблемы с проблемами, и какие проблемы у них? –

0

Это мой окончательный ответ. В основном угловой внутренний вызов функции $setDirty()NgModelController, когда вход взаимодействует, поэтому просто переопределите это!

app.directive('noDirtyCheck', function() { 
    return { 
    restrict: 'A', 
    require: 'ngModel', 
    link: postLink 
    }; 
    function postLink(scope, iElem, iAttrs, ngModelCtrl) { 
    ngModelCtrl.$setDirty = angular.noop; 
    } 
}) 
Смежные вопросы