Предотвратить ввод данных из формы $girty angularjs - программирование
Подтвердить что ты не робот

Предотвратить ввод данных из формы $girty angularjs

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

Здесь версия @acacia отвечает с использованием директивы и не использует $timeout. Это упростит ваши контроллеры.

.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>

Ответ 3

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

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

Ответ 4

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

(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);
            }
        };
    }
})();

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

Ответ 5

Вариант ответа @overthink с некоторой дополнительной валидацией и встроенной нотной скобкой для защиты от минимизации.

"use strict";

angular.module("lantern").directive("noDirtyCheck", [function () {
    return {
        restrict: "A",
        require: "ngModel",
        link: function (scope, elem, attrs, ngModelCtrl) {
            if (!ngModelCtrl) {
                return;
            }

            var clean = (ngModelCtrl.$pristine && !ngModelCtrl.$dirty);

            if (clean) {
                ngModelCtrl.$pristine = false;
                ngModelCtrl.$dirty = true;
            }
        }
    };
}]);

Ответ 6

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

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 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();
                    }
                });
            }
        };
    }]);

Ответ 7

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

app.directive('noDirtyCheck', function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: postLink
  };
  function postLink(scope, iElem, iAttrs, ngModelCtrl) {
    ngModelCtrl.$setDirty = angular.noop;
  }
})