I have to make a user creation wizard, there are 3 steps to achieve the insertion of a new user, so every step I have have a validation function to enable the next step.
As a first step for the following markup:
<div>
<div class="block block-bordered">
<div class="block-header bg-gray-lighter">
<h3 class="block-title">Details</h3>
</div>
<div class="block-content">
<div class="container-fluid">
<div class="row" style="vertical-align:middle;">
<div class="col-md-12">
<label>Organisation *</label>
</div>
</div>
<div class="row margin-bottom-20">
<div class="col-md-12">
<table style="width:100%;">
<tr>
<td>
<div class="u-table">
<div class="u-row">
<div class="u-cell">
<ui-select ng-model="$parent.CurrentUser.ConfederationOrganization" theme="select2" append-to-body="true" ng-disabled="true">
<ui-select-match>{{$select.selected.name}}</ui-select-match>
<ui-select-choices repeat="x in ConfederationList">
<div style="min-height:15px">{{x.name}}</div>
</ui-select-choices>
</ui-select>
</div>
<div class="u-cell">
<ui-select search-enabled="true" ng-model="$parent.CurrentUser.NAOrganization" ng-change="$parent.NAOrganization_Change()" theme="select2" style="min-width:100px;" append-to-body="true">
<ui-select-match>{{$select.selected.ShortName}}</ui-select-match>
<<ui-select-choices repeat="x in $parent.naOrganizationList | filter: $select.search">
<div style="min-height:15px">{{x.ShortName}}</div>
</ui-select-choices>
</ui-select>
</div>
<div class="u-cell">
<ui-select search-enabled="true" ng-model="$parent.CurrentUser.ClubOrganization" ng-change="$parent.ClubOrganization_Change()" theme="select2" style="min-width:120px;" append-to-body="true">
<ui-select-match>{{$select.selected.ShortName}}</ui-select-match>
<ui-select-choices repeat="x in $parent.clubList | clubFilter : $parent.CurrentUser.NAOrganization | filter: $select.search">
<div style="min-height:15px">{{x.ShortName}}</div>
</ui-select-choices>
</ui-select>
</div>
</div>
</div>
</td>
<td><img style="width:50px; height:50px;" ng-src="{{$parent.LogoPath}}" img-fallback alt="" /></td>
</tr>
</table>
</div>
</div>
<div class="row margin-bottom-20">
<div class="col-md-6">
<label for="surname">Surname *</label>
<div class="autosuggestion-container">
<input ng-class="$parent.CurrentUserValidationClass.Surname" kendo-auto-complete options="$parent.surnameAutoCompleteOptions" ng-model="$parent.CurrentUser.Surname" type="text" class="form-control" name="surname" placeholder='"user surname"' />
</div>
</div>
<div class="col-md-6">
<label for="email">Email *</label>
<input ng-class="$parent.CurrentUserValidationClass.Email" ng-model="$parent.CurrentUser.Email" type="text" class="form-control" name="email" placeholder='user email' />
</div>
</div>
<div class="row margin-bottom-20">
<div class="col-md-6">
<label for="firstname">First Name *</label>
<input ng-class="$parent.CurrentUserValidationClass.FirstName" type="text" class="form-control" name="firstname" ng-model="$parent.CurrentUser.FirstName" placeholder='user first name' />
</div>
<div class="col-md-6">
<div class="u-table">
<div class="u-row">
<div class="u-cell">
<label for="gender">Gender *</label>
</div>
</div>
<div class="u-row u-gender" ng-class="$parent.CurrentUserValidationClass.Gender">
<md-radio-group ng-model="$parent.CurrentUser.GenderValue" class="md-primary">
<div class="u-cell u-gender" style="padding-top:5px;">
<md-radio-button ng-value="1" aria-label="M">M</md-radio-button>
</div>
<div class="u-cell" style="padding-top:5px;">
<md-radio-button ng-value="2" aria-label="F">F</md-radio-button>
</div>
</md-radio-group>
</div>
</div>
</div>
</div>
<div class="row margin-bottom-20">
<div class="col-md-6">
<label for="dob">Date of birth *</label>
<div class="js-datetimepicker input-group date"
data-show-today-button="true" data-show-clear="true" data-show-close="true"
data-side-by-side="false" data-format="dateFormat"
datetimepicker ng-model="$parent.CurrentUser.DateOfBirth" name="dob">
<input ng-class="$parent.CurrentUserValidationClass.DateOfBirth" class="form-control" type="text" placeholder="Date of birth" />
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</div>
<div class="col-md-6">
<label for="nationality">Nationality *</label>
<div>
<ui-select ng-class="{'user-validation-error' :$parent.CurrentUserValidationClass.Nationality == 1}" ng-model="$parent.CurrentUser.Nationality" theme="select2" style="min-width:120px;" append-to-body="true">
<ui-select-match>{{$select.selected.CountryName}}</ui-select-match>
<ui-select-choices repeat="x in NationalityList">
<div style="min-height:15px">{{x.CountryName}}</div>
</ui-select-choices>
</ui-select>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="block block-bordered">
<div class="block-header bg-gray-lighter">
<h3 class="block-title">User's Data</h3>
</div>
<div class="block-content">
<div class="container-fluid">
<div class="row margin-bottom-20">
<div class="col-md-6">
<label for="username">Username *</label>
<input ng-disabled="$parent.CurrentUser.IsUser == 1" ng-class="$parent.CurrentUserValidationClass.UserName" ng-model="$parent.CurrentUser.UserName" type="text" class="form-control " name="username" placeholder='' />
</div>
</div>
<div class="row" ng-show="$parent.ProposedUserNames.length > 0">
<div class="col-md-6">
<label>Proposed Usernames</label>
<md-radio-group ng-model="$parent.CurrentUser.UserName" class="md-primary">
<md-radio-button ng-repeat="name in $parent.ProposedUserNames" ng-value="name" aria-label="{{name}}">{{name}}</md-radio-button>
</md-radio-group>
</div>
</div>
</div>
</div>
</div>
</div>
The purpose of following function is to have a boolean result to know if the validation step is completed, otherwise I'll break the wizard and I'll set a specific property to the invalid class name, so that I can highlight the related input:
$scope.stepValidationOne = function () {
var result = true;
var errorClassName = 'user-validation-error';
var okClassName = '';
var scope = this.$parent.$parent.$parent;
var preCondition = result == true;
var validateCondition = scope.CurrentUser.Surname.length > 0;
result = validateCondition;
scope.CurrentUserValidationClass.Surname = validateCondition ? okClassName : errorClassName;
validateCondition = scope.CurrentUser.FirstName.length > 0;
result = validateCondition && preCondition;
scope.CurrentUserValidationClass.FirstName = validateCondition ? okClassName : errorClassName;
validateCondition = angular.isDefined(scope.CurrentUser.DateOfBirth) && scope.CurrentUser.DateOfBirth != null;
result = validateCondition && preCondition;
scope.CurrentUserValidationClass.DateOfBirth = validateCondition ? okClassName : errorClassName;
validateCondition = scope.CurrentUser.Email.length > 0;
result = validateCondition && preCondition;
scope.CurrentUserValidationClass.Email = scope.CurrentUser.Email.length > 0 ? okClassName : errorClassName;
validateCondition = validateEmail(scope.CurrentUser.Email);
result = validateCondition && preCondition;
scope.CurrentUserValidationClass.Email = validateEmail(scope.CurrentUser.Email) ? okClassName : errorClassName;
validateCondition = scope.CurrentUser.UserName.length > 0;
result = validateCondition && preCondition;
scope.CurrentUserValidationClass.UserName = validateCondition ? okClassName : errorClassName;
validateCondition = angular.isDefined(scope.CurrentUser.GenderValue) && scope.CurrentUser.GenderValue > 0;
result = validateCondition && preCondition;
scope.CurrentUserValidationClass.Gender = validateCondition ? okClassName : errorClassName;
validateCondition = angular.isDefined(scope.CurrentUser.Nationality) && scope.CurrentUser.Nationality.CountryID > 0;
result = validateCondition && preCondition;
scope.CurrentUserValidationClass.Nationality = validateCondition ? okClassName : 1;
if (result) {
var d = $q.defer()
apiService.GetSelectetExistent(scope.CurrentUser.FirstName, scope.CurrentUser.Surname, scope.CurrentUser.DOB).success(function (response) {
$scope.SelectExistent = response;
d.resolve(!$scope.SelectExistent.length > 0);
});
return d.promise;
}
else {
return result;
}
};
this is the CurrentUser structure:
$scope.CurrentUser = {
ConfederationOrganization: $scope.ConfederationList[0],
NAOrganization: undefined,
ClubOrganization: undefined,
Surname: '',
FirstName: '',
Gender: undefined,
DateOfBirth: undefined,
Email: '',
Nationality: {},
UserName: '',
PersonId: undefined,
Teams: [],
Positions: [],
IsMainContact: false,
};
I think it can be better, but I don't how to make more readable and efficient, any suggestion?