diff --git a/modules/articles/tests/client/articles.client.controller.tests.js b/modules/articles/tests/client/articles.client.controller.tests.js
index 2e6f317f34..934acdf03c 100644
--- a/modules/articles/tests/client/articles.client.controller.tests.js
+++ b/modules/articles/tests/client/articles.client.controller.tests.js
@@ -97,7 +97,7 @@
expect(scope.article).toEqualData(mockArticle);
}));
- describe('$scope.craete()', function () {
+ describe('$scope.create()', function () {
var sampleArticlePostData;
beforeEach(function () {
@@ -119,7 +119,7 @@
$httpBackend.expectPOST('api/articles', sampleArticlePostData).respond(mockArticle);
// Run controller functionality
- scope.create();
+ scope.create(true);
$httpBackend.flush();
// Test form inputs are reset
@@ -136,7 +136,7 @@
message: errorMessage
});
- scope.create();
+ scope.create(true);
$httpBackend.flush();
expect(scope.error).toBe(errorMessage);
@@ -154,7 +154,7 @@
$httpBackend.expectPUT(/api\/articles\/([0-9a-fA-F]{24})$/).respond();
// Run controller functionality
- scope.update();
+ scope.update(true);
$httpBackend.flush();
// Test URL location to new object
@@ -167,7 +167,7 @@
message: errorMessage
});
- scope.update();
+ scope.update(true);
$httpBackend.flush();
expect(scope.error).toBe(errorMessage);
diff --git a/modules/core/client/app/config.js b/modules/core/client/app/config.js
index 98b48bffff..10e0588cb7 100644
--- a/modules/core/client/app/config.js
+++ b/modules/core/client/app/config.js
@@ -4,7 +4,7 @@
var ApplicationConfiguration = (function () {
// Init module configuration options
var applicationModuleName = 'mean';
- var applicationModuleVendorDependencies = ['ngResource', 'ngAnimate', 'ui.router', 'ui.bootstrap', 'ui.utils', 'angularFileUpload'];
+ var applicationModuleVendorDependencies = ['ngResource', 'ngAnimate', 'ngMessages', 'ui.router', 'ui.bootstrap', 'ui.utils', 'angularFileUpload'];
// Add a new vertical module
var registerModule = function (moduleName, dependencies) {
diff --git a/modules/core/client/css/core.css b/modules/core/client/css/core.css
index 861e085d37..2cbf0af6cf 100644
--- a/modules/core/client/css/core.css
+++ b/modules/core/client/css/core.css
@@ -12,12 +12,6 @@
.x-ng-cloak {
display: none !important;
}
-.ng-invalid.ng-dirty {
- border-color: #FA787E;
-}
-.ng-valid.ng-dirty {
- border-color: #78FA89;
-}
.header-profile-image {
opacity: 0.8;
height: 28px;
@@ -33,3 +27,12 @@ a:hover .header-profile-image {
padding-top: 11px !important;
padding-bottom: 11px !important;
}
+.error-text {
+ display: none;
+}
+.has-error .help-block.error-text {
+ display: block;
+}
+.has-error .help-inline.error-text {
+ display: inline;
+}
diff --git a/modules/core/client/directives/show-errors.client.directives.js b/modules/core/client/directives/show-errors.client.directives.js
new file mode 100644
index 0000000000..acfbea23d4
--- /dev/null
+++ b/modules/core/client/directives/show-errors.client.directives.js
@@ -0,0 +1,74 @@
+'use strict';
+
+/**
+ * Edits by Ryan Hutchison
+ * Credit: https://github.com/paulyoder/angular-bootstrap-show-errors */
+
+angular.module('core')
+ .directive('showErrors', ['$timeout', '$interpolate', function ($timeout, $interpolate) {
+ var linkFn = function (scope, el, attrs, formCtrl) {
+ var inputEl, inputName, inputNgEl, options, showSuccess, toggleClasses,
+ initCheck = false,
+ showValidationMessages = false,
+ blurred = false;
+
+ options = scope.$eval(attrs.showErrors) || {};
+ showSuccess = options.showSuccess || false;
+ inputEl = el[0].querySelector('.form-control[name]') || el[0].querySelector('[name]');
+ inputNgEl = angular.element(inputEl);
+ inputName = $interpolate(inputNgEl.attr('name') || '')(scope);
+
+ if (!inputName) {
+ throw 'show-errors element has no child input elements with a \'name\' attribute class';
+ }
+
+ var reset = function () {
+ return $timeout(function () {
+ el.removeClass('has-error');
+ el.removeClass('has-success');
+ showValidationMessages = false;
+ }, 0, false);
+ };
+
+ scope.$watch(function () {
+ return formCtrl[inputName] && formCtrl[inputName].$invalid;
+ }, function (invalid) {
+ return toggleClasses(invalid);
+ });
+
+ scope.$on('show-errors-check-validity', function (event, name) {
+ if (angular.isUndefined(name) || formCtrl.$name === name) {
+ initCheck = true;
+ showValidationMessages = true;
+
+ return toggleClasses(formCtrl[inputName].$invalid);
+ }
+ });
+
+ scope.$on('show-errors-reset', function (event, name) {
+ if (angular.isUndefined(name) || formCtrl.$name === name) {
+ return reset();
+ }
+ });
+
+ toggleClasses = function (invalid) {
+ el.toggleClass('has-error', showValidationMessages && invalid);
+ if (showSuccess) {
+ return el.toggleClass('has-success', showValidationMessages && !invalid);
+ }
+ };
+ };
+
+ return {
+ restrict: 'A',
+ require: '^form',
+ compile: function (elem, attrs) {
+ if (attrs.showErrors.indexOf('skipFormGroupCheck') === -1) {
+ if (!(elem.hasClass('form-group') || elem.hasClass('input-group'))) {
+ throw 'show-errors element does not have the \'form-group\' or \'input-group\' class';
+ }
+ }
+ return linkFn;
+ }
+ };
+}]);
diff --git a/modules/users/client/controllers/admin/user.client.controller.js b/modules/users/client/controllers/admin/user.client.controller.js
index 22a1dd4de4..7a017598d5 100644
--- a/modules/users/client/controllers/admin/user.client.controller.js
+++ b/modules/users/client/controllers/admin/user.client.controller.js
@@ -19,7 +19,13 @@ angular.module('users.admin').controller('UserController', ['$scope', '$state',
}
};
- $scope.update = function () {
+ $scope.update = function (isValid) {
+ if (!isValid) {
+ $scope.$broadcast('show-errors-check-validity', 'userForm');
+
+ return false;
+ }
+
var user = $scope.user;
user.$update(function () {
diff --git a/modules/users/client/controllers/authentication.client.controller.js b/modules/users/client/controllers/authentication.client.controller.js
index 2bcd6d0fe9..f5f256e6c6 100644
--- a/modules/users/client/controllers/authentication.client.controller.js
+++ b/modules/users/client/controllers/authentication.client.controller.js
@@ -12,7 +12,15 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$stat
$location.path('/');
}
- $scope.signup = function () {
+ $scope.signup = function (isValid) {
+ $scope.error = null;
+
+ if (!isValid) {
+ $scope.$broadcast('show-errors-check-validity', 'userForm');
+
+ return false;
+ }
+
$http.post('/api/auth/signup', $scope.credentials).success(function (response) {
// If successful we assign the response to the global user model
$scope.authentication.user = response;
@@ -24,7 +32,15 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$stat
});
};
- $scope.signin = function () {
+ $scope.signin = function (isValid) {
+ $scope.error = null;
+
+ if (!isValid) {
+ $scope.$broadcast('show-errors-check-validity', 'userForm');
+
+ return false;
+ }
+
$http.post('/api/auth/signin', $scope.credentials).success(function (response) {
// If successful we assign the response to the global user model
$scope.authentication.user = response;
diff --git a/modules/users/client/controllers/settings/change-password.client.controller.js b/modules/users/client/controllers/settings/change-password.client.controller.js
index d5ac3b2186..5e32e11d9b 100644
--- a/modules/users/client/controllers/settings/change-password.client.controller.js
+++ b/modules/users/client/controllers/settings/change-password.client.controller.js
@@ -5,11 +5,18 @@ angular.module('users').controller('ChangePasswordController', ['$scope', '$http
$scope.user = Authentication.user;
// Change user password
- $scope.changeUserPassword = function () {
+ $scope.changeUserPassword = function (isValid) {
$scope.success = $scope.error = null;
+ if (!isValid) {
+ $scope.$broadcast('show-errors-check-validity', 'passwordForm');
+
+ return false;
+ }
+
$http.post('/api/users/password', $scope.passwordDetails).success(function (response) {
// If successful show success message and clear form
+ $scope.$broadcast('show-errors-reset', 'passwordForm');
$scope.success = true;
$scope.passwordDetails = null;
}).error(function (response) {
diff --git a/modules/users/client/controllers/settings/edit-profile.client.controller.js b/modules/users/client/controllers/settings/edit-profile.client.controller.js
index cb985ad51b..edade73f11 100644
--- a/modules/users/client/controllers/settings/edit-profile.client.controller.js
+++ b/modules/users/client/controllers/settings/edit-profile.client.controller.js
@@ -6,19 +6,24 @@ angular.module('users').controller('EditProfileController', ['$scope', '$http',
// Update a user profile
$scope.updateUserProfile = function (isValid) {
- if (isValid) {
- $scope.success = $scope.error = null;
- var user = new Users($scope.user);
+ $scope.success = $scope.error = null;
- user.$update(function (response) {
- $scope.success = true;
- Authentication.user = response;
- }, function (response) {
- $scope.error = response.data.message;
- });
- } else {
- $scope.submitted = true;
+ if (!isValid) {
+ $scope.$broadcast('show-errors-check-validity', 'userForm');
+
+ return false;
}
+
+ var user = new Users($scope.user);
+
+ user.$update(function (response) {
+ $scope.$broadcast('show-errors-reset', 'userForm');
+
+ $scope.success = true;
+ Authentication.user = response;
+ }, function (response) {
+ $scope.error = response.data.message;
+ });
};
}
]);
diff --git a/modules/users/client/views/admin/user-edit.client.view.html b/modules/users/client/views/admin/user-edit.client.view.html
index 46c8e349f2..d09286c50b 100644
--- a/modules/users/client/views/admin/user-edit.client.view.html
+++ b/modules/users/client/views/admin/user-edit.client.view.html
@@ -1,26 +1,28 @@