ページに ng フォームがあります。フォーム内には、フォームが汚れている場合に保存ダイアログを表示する必要があるいくつかのコントロールがあります。つまり、form.$dirty = true です。ただし、フォームを汚したくないフォームにはいくつかのナビゲーション コントロールがあります。コントロールをフォームの外に移動できないとします。
参照: http://plnkr.co/edit/bfig4B
選択ボックスがフォームを汚さないようにするにはどうすればよいですか?
ページに ng フォームがあります。フォーム内には、フォームが汚れている場合に保存ダイアログを表示する必要があるいくつかのコントロールがあります。つまり、form.$dirty = true です。ただし、フォームを汚したくないフォームにはいくつかのナビゲーション コントロールがあります。コントロールをフォームの外に移動できないとします。
参照: http://plnkr.co/edit/bfig4B
選択ボックスがフォームを汚さないようにするにはどうすればよいですか?
@overthink のソリューションを使用しましたが、@dmitankin が言及した問題に遭遇しました。ただし、ハンドラーを focus イベントにアタッチしたくありませんでした。そこで代わりに、$pristine プロパティ自体をオーバーライドして、常に false を返すようにしました。IE8以下ではサポートされていない Object.defineProperty を使用してしまいました。これらの従来のブラウザーでこれを行うための回避策がありますが、私はそれらを必要としなかったため、以下のソリューションには含まれていません。
(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);
}
};
}
})();
$dirty もオーバーライドしているので、ダーティとして設定することもできません。
初期化時にのみ $pristine プロパティを false に設定すると、フォームで $setPristine() を呼び出すまで機能します。次に、コントロールの $pristine が true に戻り、入力の値を変更するとフォームが汚れます。これを避けるには、$pristine をフォーカスに設定します。
link: function(scope, elm, attrs, ctrl) {
elm.focus(function () {
ctrl.$pristine = false;
});
}
Angular は、コントロールが手付かずの場合にのみ、フォームをダーティに設定します。したがって、ここでの秘訣は、コントロールの $pristine を false に設定することです。コントローラーのタイムアウトで実行できます。
その実装でいくつかの問題に遭遇したので、これが私のものです(より複雑です):
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();
}
});
}
};
}]);