How to control the flow of function execution in AngularJS? - angularjs

I have written some code in the AngularJS controller.
The scene is as follow, I have a form which accepts all the details of the Organization including its name, its admin etc. I have written manual validations to validate the data. I have written a separate function to validate the data. Which validates all the data and depending upon the validations function return "true/false", I want to check the returned value and if the value is 'true', I want to make a call to service to enter the data into the database, BUT, If the result is false I am not supposed to call the service and show the proper alert message. BUT THE PROBLEM IS, The place from where I am calling validation function, it does not wait for function to return the value, instead It gets executed first and then the value is returned to the calling function, as a result it always shows the status as "undefined".
Validation function is as follows:
$scope.validateOrganizationForm = function(){
var phoneNumber = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;
if($scope.organization.orgName == "" || $scope.organization.orgName.length > 16){
$scope.failureAlertMessage("Please enter valid organization name of length between 1 to 16");
return false;
}else if($scope.organization.orgAddress == "" || $scope.organization.orgAddress.length > 512){
$scope.failureAlertMessage("Please enter valid organization address of length between 1 to 512");
return false;
}else if($scope.organization.orgPhoneNumber == "" || $scope.organization.orgPhoneNumber.length>13 || (!($scope.organization.orgPhoneNumber.match(phoneNumber)))){
$scope.failureAlertMessage("Please enter valid organization phone number of length between 10 to 13");
return false;
}else if($scope.organization.orgAlternatePhoneNumber != "" && ($scope.organization.orgAlternatePhoneNumber.length>13 || (!($scope.organization.orgAlternatePhoneNumber.match(phoneNumber)))) ){
$scope.failureAlertMessage("Please enter valid organization alternate phone number of length between 10 to 13");
return false;
}else if($scope.organization.orgContactPersonName == "" || $scope.organization.orgContactPersonName.length > 64){
$scope.failureAlertMessage("Please enter valid organization contact person name of length between 1 to 64");
return false;
}else if($scope.organization.orgContactPersonPhoneNumber == "" || (!($scope.organization.orgContactPersonPhoneNumber.match(phoneNumber)))){
$scope.failureAlertMessage("Please enter valid organization contact person phone number of length between 10 to 13");
return false;
}else if($scope.organization.orgContactPersonEmailId == "" || $scope.organization.orgContactPersonEmailId == undefined || $scope.organization.orgContactPersonEmailId.length > 64){
$scope.failureAlertMessage("Please enter valid organization contact person email id of length between 1 to 64");
return false;
}else if($scope.organization.orgDescription == "" || $scope.organization.orgDescription.length > 256){
$scope.failureAlertMessage("Please enter valid organization description of length between 1 to 256");
return false;
}else if($scope.organization.userVo.username == "" || $scope.organization.userVo.username.length > 64){
$scope.failureAlertMessage("Please enter valid organization admin username of length between 1 to 64");
return false;
}else if($scope.organization.userVo.emailId == "" || $scope.organization.userVo.emailId.length > 128){
$scope.failureAlertMessage("Please enter valid organization admin email Id of length between 1 to 128");
return false;
}else{
console.log("All the fields are validated except validating duplications, lets check it now");
$scope.checkOrgName().then(
function(orgNameStatus){
console.log("can we use this org name :"+orgNameStatus);
if(orgNameStatus==false){
console.log("Organziation name is already present in the database");
return false;
}else if(orgNameStatus){
$scope.isOrgAdminUsernameAvailable = $scope.checkOrgAdminUsername().then(
function(orgAdminUsernameStatus){
console.log("Can we use this username for admin: "+orgAdminUsernameStatus);
if(orgAdminUsernameStatus == false){
console.log("org admin username is already present in the database");
return false;
}else if(orgAdminUsernameStatus){
$scope.isAdminEmailIdAvailable = $scope.checkOrgAdminEmailId().then(
function(orgAdminemailIdStatus){
console.log("Can we use this admin email id: "+orgAdminemailIdStatus);
if(orgAdminemailIdStatus == false){
console.log("Org admin email id is already present in the database");
return false;
}else if(orgAdminemailIdStatus){
console.log("All the three fields(orgName,orgAdminUsername,orgAdminEmailId) are checked for duplication, everything is validated sucessfully");
return true;
}
});
}
});
}
});
}
return true;
}
And here is the calling function:
$scope.addOrganization = function(){
console.log("Command in add Org");
var validationStatus = $scope.validateOrganizationForm(); (Here I am calling validation function)
console.log("Add form validation status: "+validationStatus); (This always gives me undefined...)
if(validationStatus){
console.log("Form validated successfully, We can add organization safely");
OrganizationService.addOrganization($scope.organization).then(
function(data){
$scope.successAlertMessage("Organition Added successfully");
$scope.resetAddOrgForm();
},
function(errResponse){
$scope.successAlertMessage("There was an error adding organization");
}
);
}else{
console.log("Add form validation failed");
}
}
Can I use .then() for this, I tried that too, but it says I am not returning any promise instead I am just returning a plain boolean value, How can I send the promise if I have to use .then()..??

Related

Restrict double minus in mui number textfiled

Currently, Number type inputs accepting double minus (i.e: --1). But I want only one - sign. If user press another minus then it should preventDefault().
Found a solution here. But it has some edge cases like, if user input '-123' and then go back and remove the '-' then user can't give the '-' again.
Since such values (-786-6, --712, ...) are allowed in TextField of type="number"
What I did is changing the textField proprety type from number to text, yes we'll accept strings but the user will be forced to enter a valid number.
Let's create a useState hook for the TextField input :
const [entredValue,setEntredValue] = useState('');
Then each time we verify if the entred input is a valid number before updating entredValue. this is a function made for that :
function restrict(test) {
if (test == "") return true;
if (test.length == 1) {
if (isNaN(test[0]) && test[0] !== "-") return false;
}
var found = 0;
for (let i = 0; i < test.length; i++) {
if (test[i] === ".") found++;
}
if (found > 1 || test == "-.") return false;
if (
test.length > 1 &&
isNaN(test[test.length - 1]) &&
test[test.length - 1] !== "."
)
return false;
let result = test.substr(0, test.length - 1);
if (test.length > 2 && isNaN(result)) return false;
return true;
}
Then update the state value this way :
<TextField
onChange={(event) => {
if (restrict(event.target.value)) {
setEntredValue(event.target.value);
}}}
/>
finally when you have to use entredValue:
parseFloat(entredValue); // always a valid number

Vapor 4/Fluent, function with nested database lookup to return return EventLoopFuture<bool>

I'm attempting to write a function that takes in my UserModel, and preforms a couple of checks to see if the user
Is locked
Hasn't attempted too many logins within a time period.
and then returns a Boolean indication of the result.
The lookups work within my Authentication process. But I wanted to break out the code that determines if the user is allowed to (attempt) login so I can use it in more than one place without repeating code.
However (being new to Vapor/Swift) i am getting an error and I cannot work out what I'm doing wrong:
Cannot convert return expression of type 'EventLoopFuture' to return type 'Bool'
The Error is on the line }.all().map { (separated onto a line by itself so its easier to find).
Database structure wise I have 2 tables involved:
UserAccess which holds my user profile details (how many bad attempts this user can have, and how far back in the log do we look for login attempts)
UserLog, which hows the login attempts for each user and when they made the attempt
This is my code snippet so far:
func CanUserLogin(user: UserModel, req: Request) -> EventLoopFuture<Bool> {
if(!(user.locked ?? false)) {
let userProfileId = user.userprofile
return Usertype.query(on: req.db)
.filter(\.$profilenum == userProfileId)
.first().map { useraccess in
let badloginperiod = Double((useraccess!.badloginperiod ?? 0) * -1 * 60) // convert minutes to seconds (we need a negative number)
let lookUpDate = Date().addingTimeInterval(badloginperiod)
return Userlog.query(on: req.db).group(.and) {
and in
and.filter(\.$username == user.username)
and.filter(\.$datecreated >= lookUpDate)
}.all().map {
UserLogs -> Bool in
let value = userLogs.count
// the account is locked or the max attempts for the time peroid
if(value >= (useraccess.maxloginattempts ?? 3)) {
return false
} else {
return true
}
}
}
}
}
Any direction would be greatly appreciated.
You tried to return EventLoopFuture from map block, but you can return only non-future values from it. So instead of map you have to use flatMap on Usertype query.
Checkout this code
func canUserLogin(user: UserModel, req: Request) -> EventLoopFuture<Bool> {
guard user.locked != true else {
return req.eventLoop.makeFailedFuture(Abort(.badRequest, reason: "User is locked"))
}
let userProfileId = user.userprofile
return Usertype.query(on: req.db)
.filter(\.$profilenum == userProfileId)
.first()
.unwrap(or: Abort(.forbidden, reason: "No access"))
.flatMap { userAccess in
let badloginperiod = Double((useraccess.badloginperiod ?? 0) * -1 * 60) // convert minutes to seconds (we need a negative number)
let lookUpDate = Date().addingTimeInterval(badloginperiod)
return Userlog.query(on: req.db).group(.and) {
$0.filter(\.$username == user.username)
$0.filter(\.$datecreated >= lookUpDate)
}.all().map { attempts -> Bool in
// the account is locked or the max attempts for the time peroid
if attempts.count >= (userAccess.maxloginattempts ?? 3) {
return false
} else {
return true
}
}
}
}

single requirement in parsley error message %s1

Hi I have a custom validator with 2 requirements(arguments/paramaters) in parsley.js
For the error message I only want to display one of the requirements but I cannot work out how
messages: {en: 'You must choose at least one language with %s'},
I thought %s1 or %s0 might work but they don't
%s results in this message:
You must choose at least one language as [native,enrolment_form_new_instruction_languages_proficiency]
but I just want
You must choose at least one language as native
here is my full validator in case that helps you answer:
Parsley.addValidator('oneChildEquals', {
requirementType: ['string', 'string'],
validateString: function(_value, requirement, requirement2, instance) {
var $inputs = $(instance.element).find("select.language-proficiency");
var valid = false;
$inputs.each(function(i){
if($(this).val() == requirement){
valid = true; // one input has the target value (requirement2)
return false; //break out of the loop
}
});
// no input has the target value (requirement2)
return valid;
},
messages: {en: 'You must choose at least one language with %s'},
});
I have written a solution, probably could be improved, but I don't even know if I need this now. Anyway in case anyone else does, you can just add this code:
if(typeof(string) === 'string' && typeof(parameters) === 'string' && parameters.match(/^\[.*\]$/) && string.match(/\%s\d/)){
//parameters are an array of values and string is trying to access them individually with %s1 to get first etc
var paramsArray = parameters.slice(1, parameters.length-1).split(',');
var interpolations = string.match(/\%s\d/g);
for(var j = 0; j < interpolations.length ; j++){
var interpolation = interpolations[j];
var number = parseInt(interpolation.replace("%s", ''));
if(isNaN(number)){
string = string.split(interpolation).join(interpolation + '[not a valid interpolation]');
}else {
var val = paramsArray[number-1];
if(typeof(val) === 'undefined'){
val = interpolation + '[not a valid interpolation]';
}
string = string.split(interpolation).join(val);
}
}
return string
}
after this code in the source
formatMessage: function formatMessage(string, parameters) {
if ('object' === _typeof(parameters)) {
for (var i in parameters) {
string = this.formatMessage(string, parameters[i]);
}
return string;
}
and before
return 'string' === typeof string ? string.replace(/%s/i, parameters) : '';
Then it supports things like
Parsley.addValidator('testParsley', {
requirementType: ['string','string'],
validateString: function(_value, requirement, requirement2) {
return (_value === requirement || _value === requirement2);
},
messages: {en: 'test parsley this field must equal %s1 or %s2'}
});

How to implement a for loop with if statements

for (let i = 0 ; i<user.length;i++)
{
if (this.username === user[i].username && this.password === user[i].password){
this.title="Successfully login your account";
this.router.navigate(['/home']);
return;
} else {
this.title = "Please check your username and password (or) create New Account in Register";
return;
}
}
return user[i];
}
your else statement should not be in the loop. you else statement will execute as soon as you hit the first user. set a userVerifiedFlg = false; before the loop, and then check to see if it is still false after checking against all users.

Angularjs filter multi level object

I need to create a filter in angularjs
My data looks something like this:
[{
name: 'account1',
accounts: [
{
name: 'account2',
accounts: []
},
{
name: 'account3',
accounts: [
{
name: 'account4',
accounts: []
}
]
}
]
}]
I need the filter return the full object if I use account4 for the search text. Or just the first 2 levels if I use account2 etc.
I have searched all over but cant find anything like this and have no idea where to start.
You'll need to create a custom filter to do what you're requesting. A controller filter will only allow you to provide an expression to include or exclude an ng-repeat item.
A custom filter will allow you to modify the model dynamically. You can splice the json object accordingly.
I'll provide an example when I'm back in in front of a pc.
I got it figured out finally. Here is the custom filter I created in case anyone else finds it useful:
.filter('accountsFilter', function() {
return function(items, searchStr) {
function filterAccounts(account, str) {
//if account name matches
if (account.name && account.name.toLowerCase().indexOf(str.toLowerCase()) > -1) {
//expand parent account
if (account.accounts && account.accounts.length > 0) account.expand = true;
//return account
return account;
} else
//account name doesnt match. check sub accounts
if (account.accounts && account.accounts.length > 0) {
//has accounts
var fa = [];
angular.forEach(account.accounts, function(act, k) {
var a = filterAccounts(act, str);
//if account was returned
if (a !== false) {
//add account to filtered accounts
fa.push(act);
}
});
//add accounts to parent account
account.accounts = fa;
//if there are sub-accounts
if (fa.length > 0) {
//make sure account is expanded to show sub accounts
if (account.accounts && account.accounts.length > 0) account.expand = true;
//return account
return account;
//no sub accounts left
} else {
//check and return if main account matches
return filterAccounts(account, str);
}
//no matches
} else {
return false;
}
}
//copy accounts list to prevent original being altered
var accounts = angular.copy(items);
var filtered = [];
//loop through accounts list
angular.forEach(accounts, function(account) {
//check if current account matches
var a = filterAccounts(account, searchStr.name);
if (a) {
//add to filtered list
filtered.push(a);
}
});
return filtered;
};
})

Resources