I am using a for loop to check whether the user has attached the required documents or not. Based on the success I am submitting it to the server. I would like to make it simple. Even the validation passes it should submit the data only once instead of many times.
I have put the submit inside the loop for each success it will submit the data.
can anyone suggest me how I can make it simpler?
function validateFile () {
if (vm.imageURIs.length > 0) {
for (var i = 0; i < vm.imageURIs.length; i++) {
var data = vm.imageURIs[i];
if (data.img && data.img.length > Config.ENV.FILE_SIZE) {
var fileName = data.name || vm.i18n.documentNumber + (i + 1);
Toast.message($translate.instant('DOCUMENTMAXSIZE', { name: fileName }));
} else if (data.document_required === true && data.img.length === 0) {
Toast.message($translate.instant('DOCUMENTREQUIRED', {name: data.name}));
} else {
applyScheme();
}
}
} else {
applyScheme();
}
}
Try putting
break;
after
applyScheme();
Reference: https://www.w3schools.com/js/js_break.asp
Related
I am running tests using Cypress.
I have an array of Litecoin addresses. I am trying to set first in the input. Then submit the form.
If the address is duplicate then a notification is displayed and submit button will be not visible. The same I want to set for the second element and so on till end of the array.
I tried recursive function:
function runTillElementFound (totalCount, currentCount, litecoin_addresses)
{
var self = this;
if (currentCount < totalCount) {
return cy.get('body').then(($body) =>
{
if ($body.find(dash_page.save_wallet_circle_btn)) {
//if there is save button then set address and submit form
cy.log('taken address: ' + litecoin_addresses[ currentCount ]);
dashact.fill_wallet(litecoin_addresses[ currentCount ]);
cy.log('address is filled');
dashact.submit_wallet(true, 0);
self.runTillElementFound(totalCount, currentCount++);
}
});
} else {
return false; //if element not present after Max count reached.
}
I try to call it:
it('Set wallet', () =>
{
cy.log('this is array length: ' + litecoin_addresses);
runTillElementFound(20, 0, litecoin_addresses);
/* comact.submit_form(true, 1);
let ltc_address = promisify(dashact.get_wallet_value());
cy.log('this is address: ' + ltc_address);
//close popup and check that it is closed:
popact.submit_payment(); */
});
However I receive undefined:
I have also tried non recursive function:
for (var i = 0; i < litecoin_addresses.length; i++) {
cy.log('taken address: ' + litecoin_addresses[ i ])
if (litecoin_addresses[ i ] == wallet_before_edit || litecoin_addresses[ i ].length == 0 || litecoin_addresses[ i ].startsWith('ltc')) {
continue;
}
else {
cy.log('this is curent i: ' + i);
dashact.fill_wallet(litecoin_addresses[ i ]);
dashact.submit_wallet(true, null);
cy.get('body').then(($body) =>
{
// synchronously query from body
// to find which element was created
if ($body.find(com_page.not_message).length) {
// error was found, do something else here
cy.log('error was found');
}
else {
cy.log('error not found');
// input was not found, do something else here
i = litecoin_addresses.length;
cy.log('current i value: ' + i);
}
})
}
However it for sure, does not work, as i inside promise has one valued but in the loop it still remains the same.
If you use a specific array in your test code, you can easily get the length of the array by using the .lenght and access its elements by using the for loop.
I'm getting an array of Strings, and if the array has items I want to do one thing and if not I want to do the other. I'm not sure how to check if the array is empty of not. Also when stepping through my code in chrome debugger even if the array has items in it the length is still 0 so I can't use formErrors.length > 0.
Here's my code for getting the errors. This works fine and returns an array of error strings or an empty array:
var formErrors = validateFormData(formData);
function validateFormData(data) {
var errors = [];
if (data["title"].length == 0) {
errors["title"] = "Project title required";
}
if (data["client"].length == 0) {
errors["client"] = "Client name required";
}
if (data["date"].length == 0) {
errors["date"] = "Date required";
} else if (!isValidDateFormat(data["date"])) {
errors["date"] = "Date format invalid - Format: dd/mm/yyyy";
}
if (data["status"] == "") {
errors["status"] = "Please select current status for this project";
}
if (data["type"] == "") {
errors["type"] = "Please select a project type";
}
if (data["extras"].length == 0) {
errors["extras"] = "You must select at least one extra for this project";
}
return errors;
}
Then I want to do one thing if there's no errors and another if there is. But this is the bit that won't work for me.
if (formErrors !== {}) {
displayFormErrors(formErrors);
event.preventDefault();
}
else {
clearForm();
}
I've tried multiple ways and nothing has worked so far. Any help is appreciated, thank you!
EDIT
I can't use the .length on the array cause the length is 0 even when it has data.
Screenshot of chrome debugger
I'm slightly confused about what people are asking sorry, i'm not an expert here is my full code to get a better understanding of what i'm trying to do.
$(document).ready(function () {
$('#submit').on("click", onSubmitForm);
function onSubmitForm(event) {
clearErrorMessages();
var formData = getFormData();
var formErrors = validateFormData(formData);
if (formErrors) {
displayFormErrors(formErrors);
event.preventDefault();
}
else {
clearForm();
// Do other stuff
}
}
function clearForm() {
$('#title').val("");
$('#client').val("");
$('#date').val("");
$('#status').val("planning");
$('#description').val("");
$('.type').prop('checked', false);
$('.extra').prop('checked', false);
$('#title').focus();
}
function clearErrorMessages() {
$(".uk-text-danger").html("");
}
function getFormData () {
var data = [];
data["title"] = $('#title').val();
data["client"] = $('#client').val();
data["date"] = $('#date').val();
data["status"] = $('select#status option:selected').val();
data["description"] = $('#description').val();
if ($("input[name='type']:checked").length > 0) {
data["type"] = $("input[name='type']:checked").val();
}
else {
data["type"] = "";
}
data["extras"] = [];
$.each($("input[name='extras[]']:checked"), function(index, radio) {
data["extras"].push(radio.value);
});
return data;
}
function validateFormData(data) {
var errors = [];
if (data["title"].length == 0) {
errors["title"] = "Project title required";
}
if (data["client"].length == 0) {
errors["client"] = "Client name required";
}
if (data["date"].length == 0) {
errors["date"] = "Date required";
} else if (!isValidDateFormat(data["date"])) {
errors["date"] = "Date format invalid - Format: dd/mm/yyyy";
}
if (data["status"] == "") {
errors["status"] = "Please select current status for this project";
}
if (data["type"] == "") {
errors["type"] = "Please select a project type";
}
if (data["extras"].length == 0) {
errors["extras"] = "You must select at least one extra for this project";
}
return errors;
}
function displayFormErrors(errors) {
for (var field in errors) {
var errorElementId = field + "Error";
$('#' + errorElementId).html(errors[field]);
}
} });
Sorry if this is too much i'm not sure what else to do.
An empty array, string or object is "falsy" in JavaScript.
That is, you can pass the array, string or object directly into the if conditional and it will run depending on if something is in there or not.
if ([]) {
// this will never run
}
if ('') {
// this won't run either
}
if ({}) {
// nor will this
}
var errors = {}; inside the validateFormData function.
And then compare the the object like this.
if (JSON.stringify( formErrors ) !== '{}') { //do something}else { //do something}
Where are you verifying if the formErrors is empty? This verification (the if-else) should be inside the function which submits the form.
Also try using:
if (formErrors.length > 0)
instead of:
if (formErrors !== {})
In my angular app, I have an array called "cart" which can be empty or have some objects.I am trying to display Refer button in my page whenever the array is empty.When the array has any objects, it should display the Buy button though.In my case, when the array is not empty,it can have maximum of two objects- Now and Later or any one based on the scenarios.
I am trying something like this but in both the cases Refer button is being displayed.
My html-
<div class="col-md-12">
<button *ngIf="clickToRefer">Buy</button>
<button *ngIf="!clickToRefer">Refer</button>
</div>
In my .ts file-
if (data) {
for (var i = 0; i < data.result.cart.length; i++) {
var obj = data.result.cart[i];
if ((obj !== undefined) &&
(data.result.cart.length > 0) &&
((obj.option == 'Now') || (obj.option == 'Later'))) {
this.clickToRefer = true;
} else {
this.clickToRefer = false;
}
}
this.router.navigate(['/home']);
}
inside export i have declared-
clickToRefer : boolean;
Here , data has the entire response which has cart array.I am getting the response properly.
Can someone help me knowing where I am going wrong.
I think it's just a JS logic issue, not angular.
Inside of the for loop "obj" can't be undefined and the length of the array will always be > 0 so your sample of code is the same as:
if (data) {
for (var i = 0; i < data.result.cart.length; i++) {
var obj = data.result.cart[i];
if ((obj.option == 'Now') || (obj.option == 'Later')) {
this.clickToRefer = true;
} else {
this.clickToRefer = false;
}
}
this.router.navigate(['/home']);
}
I suspect that your data.option is never 'Now' or 'Later'?
I have scoured the other question/answer for this and implemented everything and I still cannot access the values of the object. Here's the code I am using:
function apply_voucher(voucher) {
var dates = $.parseJSON($("[name='dates']").val());
var voucher_yes_no = new Array();
var voucher_reduction = new Array();
if(voucher.length > 0)
{
$.each(dates, function(room_id, these_dates) {
$.post('/multiroom/check_voucher/'+voucher+'/'+room_id, function(result) {
if(result.result == 'ok') {
voucher_yes_no.push('yes');
voucher_reduction.push(result.voucher_reduction);
} else {
voucher_yes_no.push('no');
}
}, 'json');
});
// check if there are any yes's in the array
if('yes' in voucher_yes_no) {
console.log("no yes's");
} else {
console.log(voucher_reduction);
console.log(typeof voucher_reduction);
for (var prop in voucher_reduction) {
console.log(prop);
console.log(voucher_reduction[prop]);
if (voucher_reduction.hasOwnProperty(prop)) {
console.log("prop: " + prop + " value: " + voucher_reduction[prop]);
}
}
}
}
}
Apologies for the constant console logging - I'm just trying to track everything to make sure it's all doing what it should. The console output I get from this is below:
...which shows the object containing one value, "1.01" and my console.log of the typeof it to make sure it is actually an object (as I thought I was going mad at one point). After this there is nothing from inside the for-in loop. I have tried jquery's $.each() also to no avail. I can't understand why nothing I'm trying is working!
It does not work because the Ajax call is asynchronous!
You are reading the values BEFORE it is populated!
Move the code in and watch it magically start working since it will run after you actually populate the Array!
function apply_voucher(voucher) {
var room_id = "169";
var dates = $.parseJSON($("[name='dates']").val());
var voucher_reduction = new Array();
$.post('/multiroom/check_voucher/'+voucher+'/'+room_id, function(result) {
if(result.result == 'ok') {
voucher_reduction.push(result.voucher_reduction);
}
console.log(voucher_reduction);
console.log(typeof voucher_reduction);
for (var prop in voucher_reduction) {
console.log(prop);
console.log(voucher_reduction[prop]);
if (voucher_reduction.hasOwnProperty(prop)) {
console.log("prop: " + prop + " value: " + voucher_reduction[prop]);
}
}
}, 'json');
}
From what it looks like, you plan on making that Ajax call in a loop. For this you need to wait for all of the requests to be done. You need to use when() and then(). It is answered in another question: https://stackoverflow.com/a/9865124/14104
Just to say for future viewers that changing the way I did this to use proper deferred objects and promises, which blew my head up for a while, but I got there! Thanks for all the help, particularly #epascarello for pointing me in the right direction :) As soon as I started doing it this way the arrays began behaving like arrays again as well, hooray!
Here's the final code:
function apply_voucher(voucher) {
var booking_id = $("[name='booking_id']").val();
var dates = $.parseJSON($("[name='dates']").val());
if(voucher.length > 0) {
var data = []; // the ids coming back from serviceA
var deferredA = blah(data, voucher, dates); // has to add the ids to data
deferredA.done(function() { // if blah successful...
var voucher_yes_no = data[0];
var voucher_reduction = data[1];
if(voucher_yes_no.indexOf("yes") !== -1)
{
console.log("at least one yes!");
// change value of voucher_reduction field
var reduction_total = 0;
for(var i = 0; i < voucher_reduction.length; i++) {
reduction_total += voucher_reduction[i];
}
console.log(reduction_total);
}
else
{
console.log("there are no yes's");
}
});
}
}
function blah(data, voucher, dates) {
var dfd = $.Deferred();
var voucher_yes_no = new Array();
var voucher_reduction = new Array();
var cycles = 0;
var dates_length = 0;
for(var prop in dates) {
++dates_length;
}
$.each(dates, function(room_id, these_dates) {
$.post('/multiroom/check_voucher/'+voucher+'/'+room_id, function(result) {
if(result.result == 'ok') {
voucher_reduction.push(result.voucher_reduction);
voucher_yes_no.push('yes');
} else {
voucher_yes_no.push('no');
}
++cycles;
if(cycles == dates_length) {
data.push(voucher_yes_no);
data.push(voucher_reduction);
dfd.resolve();
}
}, 'json');
});
return dfd.promise();
}
Can you show how voucher_reduction is defined?
I am wondering where the second line of the debug output comes from, the one starting with '0'.
in this line:
console.log(vouncher_reduction[prop]);
^
The name of the variable is wrong (then) and probably that is breaking your code.
I think there are no problem with your loop.
But perhaps with your object.
Are you sure what properties has enumerable ?
Try to execute this to check :
Object.getOwnPropertyDescriptor(voucher_reduction,'0');
If it return undefined, the property was not exist.
Sorry for the lack of description in title, it's difficult to explain.
So I have a simple signup page and I made a bunch of functions in my code that check things such as the username length, make sure the passwords match, etc..
The problem is, if there is more than one error in the users input, it only displays one error at the bottom.
HEre is the JSfiddle: http://jsfiddle.net/LCBradley3k/xqcJS/19/
Javascript:
$('#join').on('click', function () {
var correct = true;
$('input[type="text"], input[type="password"]').each(function (indx) {
var $currentField = $(this);
if ($currentField.val() === '') {
$currentField.addClass('empty');
correct = false;
$currentField.one('keydown', function () {
$currentField.removeClass('empty');
});
} else {
$currentField.removeClass('empty');
}
});
function userLength() {
var x = $('input[name="user"]').val();
if (x.length < 6) {
$('#answer').html('Less than six characters.');
$('input[name="user"]').addClass('empty');
return false;
} else {
return true;
}
}
function passwordCheck() {
var x = $('input[name="password"]').val();
var y = $('input[name="passwordcheck"]').val();
if (x === y) {
return true;
} else {
$('#answer').html('Two different passwords');
$('input[name="password"], input[name="passwordcheck"]').addClass('empty');
return false;
}
}
function validateForm() {
var x = $('input[name="email"]').val();
if (x.indexOf('#') !== -1 && x.lastIndexOf(".") !== -1) {
return true;
} else {
$('#answer').html('Not a valid email');
$('input[name="email"]').addClass('empty');
return false;
}
}
if (correct) {
if (userLength()) {
if (passwordCheck()) {
if (validateForm()) {
$('#answer').html('Thank You!');
setTimeout(function () {
$('.inputs').hide("slide", {
direction: "up"
}, 1000);
}, 2000);
}
}
}
} else {
$('#answer').html('Please fill highlighted fields.');
}
});
You can see that all of them edit the #('#answer') div with .html(). But only one is displayed when there is more than one error. Once that error is fixed and the button is pressed, it will then display the next error. I want them all to be displayed in a list.
I created a fiddle that may be of some help. The idea is to create an array with the errors in it like so:
var errors = [];
errors.push("Error 1");
errors.push("Error 2");
As you step through the validation, every time an error is encountered you simply push the error string onto the array. When you get to the end of the validation you need to compile these errors into html like that can be appended to your $('#answer') element. In this case the items are compiled into an unordered list. You can change this to fit your needs.
var content = "<ul>";
for(var a = 0, len = errors.length; a < len; a++) {
content += "<li>" + errors[a] + "</li>";
}
content += "</ul>";
$('#answer').html(content);
The html is built dynamically and stored in the variable content. content is then appended to your html element that displays the errors (in your case answer).
You have 2 issues with doing what you want.
First, you are only continuing your checks if the first one passes, due to your nested if statements.
Second, you are replacing the #answer html with the message, which means even if you do each check, you will only see the results of the last one.
A simple fix would be to un-nest your if statements, and keep a variable that tracks the overall pass state. Secondly, instead of using .html(), use .append(), but make sure to clear out #answer before starting your checks.
correct &= checkFilled();
correct &= userLength();
correct &= passwordCheck();
correct &= validateForm();
if (correct) {
// ...
}
Fiddle: http://jsfiddle.net/jtbowden/9cFKW/
Note: I made your form filled check it's own function to work better with this method.
You can do some more fancy things, like pushing error messages on an array, and then checking the array for errors at the end and appending all of the messages, but this should get you started.