diff --git a/NEWS b/NEWS
index 847682c64..0ad9ca742 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,7 @@ Enhancements
Bug fixes
- [web] fixed attachment path when inside multiple body parts
- [web] fixed email reminder with attendees (#4115)
+ - [web] prevented form to be marked dirty when changing password (#4138)
- [core] cherry-picked comma escaping fix from v2 (#3296)
- [core] fix sogo-tool restore potentially crashing on corrupted data (#4048)
- [core] handle properly mails using windows-1255 charset (#4124)
diff --git a/UI/Templates/PreferencesUI/UIxPreferences.wox b/UI/Templates/PreferencesUI/UIxPreferences.wox
index 131046368..1e6783c98 100644
--- a/UI/Templates/PreferencesUI/UIxPreferences.wox
+++ b/UI/Templates/PreferencesUI/UIxPreferences.wox
@@ -233,13 +233,13 @@
-
+
-
+
diff --git a/UI/WebServerResources/js/Common/sgNoDirtyCheck.directive.js b/UI/WebServerResources/js/Common/sgNoDirtyCheck.directive.js
new file mode 100644
index 000000000..a19381591
--- /dev/null
+++ b/UI/WebServerResources/js/Common/sgNoDirtyCheck.directive.js
@@ -0,0 +1,33 @@
+/* -*- Mode: js; indent-tabs-mode: nil; js-indent-level: 2 -*- */
+
+(function() {
+ 'use strict';
+
+ angular
+ .module('SOGo.Common')
+ .directive('sgNoDirtyCheck', sgNoDirtyCheck);
+
+ /*
+ * sgNoDirtyCheck - prevent input from affecting the form's pristine state.
+ * @restrict attribute
+ */
+ function sgNoDirtyCheck() {
+ 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;
+ }
+ }
+ };
+ }
+
+})();