I've been putting together a sign-up form that is essentially broken up into 3 parts; you fill out your name, email, username, etc. then your chosen options (colour, intro text, etc.), then your address details. Each of these steps has at least one field that utilises ajax to check its validity; i.e. checking for duplicate emails or usernames, suggesting alternate page titles, etc.
These ajax functions are triggered (after a brief delay) on keyup input blur, but it has only just occurred to me that I also want to validate the inputs when someone clicks to move on to the next step of the sign-up. The method I'd usually use is to trigger a blur on all fields of the current sign-up step and, if any have an .error attached, don't allow the user to move on; however triggering a blur on the fields with ajax listeners attached to them means that they don't immediately return an error.
Handily, I'm not using any kind of plugin - I've coded everything myself. When the ajax fields are checking the validity of their input, they do have a .loading class attached that will eventually turn into either an .okay or .error class, but on some screens there are 2-4 ajax-checked fields at once, so I need to wait for all of them to validate before moving on.
My current validation function is uber-simple:
$(document).on('click', '.step button.validate', function() {
var currentStep = $(this).closest('.step');
// Let's try to trigger those errors ON PORPOISE
currentStep.find('input, select, textarea').trigger('blur');
if (currentStep.find('.error').length) {
// No dice.
alert('This is bad, yo.');
return false;
}
// Everything looks hunky-dory; the form should submit as normal
gotoNextStep();
});
TL;DR I'm trying to figure out how to 'wait' for all of my ajaxified fields to return a response before doing anything.
Worth noting:
The whole thing is wrapped inside one big <form> element. This doesn't get submitted with each step; only at the end, when each step has been provisionally validated. It (very basically) looks like this: http://jsfiddle.net/zVAxs/ (HTML markup only for illustration of structure).
Any help or pointers in the right direction would be greatly appreciated.
I'm not really sure that it is what you are looking for, but $.ajaxSetup({async: false}) is what I can think of. Try using it at the start of your code and this way the code will wait for the answer of the request
If you can call the ajax validation functions explicitly (not by triggering blur) then jQuery's
when() function may help you: http://api.jquery.com/jQuery.when/
From jQuery sample:
$.when( $.ajax( "/validation1.php" ), $.ajax( "/validation2.php" ) ).then(function( a1, a2 ) {
// a1 and a2 are arguments resolved for the validation1 and validation2 ajax requests, respectively.
// Each argument is an array with the following structure: [ data, statusText, jqXHR ]
gotoNextStep();
});
then() function is only executed if all ajax request have completed successfully.
Related
I need to pass in form variables via AJAX every time a select box value is changed, and get a returned string from the AJAX call to display on the page. Here's the situation:
I built a form which is dynamically built by the user for a set of compliance rules. This allows the user to have multiple select boxes to generate a logic statement such as the following:
(
( 6779 AND 10852 AND 10845 )
AND
(
( 8260 AND 8258 )
)
)
OR
( 6780 OR 10845 OR 8258 OR 12893 )
I've written a function that returns this logic statement as a string after submission of the form, but would like to dynamically populate a div (#logicblock) on the form page BEFORE submitting, so that the user can verify the logic before submission of the information into our database.
I tried to use the following:
('##logicblock').load("#getmodel('model.compliance').BuildLogic(rc)#", function(response){
$('##logicblock').html(response);
})
... but this does not properly pass in the RC scope into my model. I've searched and can't find a way that makes sense to me to send the entire form scope into a method that returns a value for display on the page.
I got it figured out. Because the form fields are dynamically generated, I found that I couldn't use a $('select').change() event to call the method, so I wrote a handler method to generate the data and serialized the form to pass in to the handler. I was able to use the following to get the desired response:
function updateLogicBlock(){
var serialform = $('form').serialize();
$.get("#event.buildLink('handler.buildComplianceLogic')#?" + serialform,
function(data) {
$('##logicblock').html(data);
});
};
Then I simply added onChange="updateLogicBlock();" to every select box on the form.
I was trying to change _onFormReset method in YUI (or Alloy UI) - I think it is common JavaScript (OOP) thing, but I am a noob in JS OOP and YUI (been using some JQuery till now) - how can I change functionality of method (keeping other methods as they are)?
for example;
Currently method looks like:
_onFormReset: function(event) {
var instance = this;
instance.resetAllFields();
},
(src: http://alloyui.com/api/files/alloy-ui_src_aui-form-validator_js_aui-form-validator.js.html#l1192)
But I want it to be like:
_onFormReset: function(event) {
var instance = this;
instance.resetAllFields();
/* PSEUDO:
**a.) action is logged (ajax call to DB)
b.) all fields in form are reset (default behaviour) + form get's a new anti CSFR UID via ajax
c.) notification is shown (like that message in my example but let's say: Form reseted!)
d.) (Submit button reappears)**
...
*/
},
I tried something like:
/* trying to hijack thingZ */
var FormReset = Y.Component.create({
// component name
NAME : 'form-validator-reset',
EXTENDS : Y.Base,
// Base component's method which extends
prototype : {
_onFormReset: function(event) {
var instance = this;
instance.resetAllFields();
Y.one("#submitit").setHTML("<h4>Thanks, form submitted ok</h4>");
}
}
});
But with no success.
I looked at documentation and wasn't able to find a way, also it seems like I am missing OOP Javascript basics :(
Can somebody help me "catch the fish" :)
Trying to learn good (OOP) JavaScript for a long time, reading a lot online, but best way for me is learning by coding and now I am really stuck...
So my wish is to have something that I can use in all my forms for when reset button is clicked (in same way I would also change Submit) - OOP method - attached to default reset function, upgrading it in "my" way.
It looks like you're trying to tackle this the wrong way. Unless you're just doing this as an exercise in overriding a method you really shouldn't do that if all you're trying to do is print out a thank you.
Also if you're looking to thank the user for submitting you should be trying to do that when the user submits the form, not when the form is reset. To do this you'd subscribe a function to the 'submit' event of the form.
A.one("#my_form").on("submit", function() {
Y.one("#submitit").setHTML("<h4>Thanks, form submitted ok</h4>");
});
Ok, after rethinking it, I suppose preventDefault is ok for me (I will try to learn OOP JS with other cases :)).
This is (a n00by) solution:
add #resetit to reset button
add code:
var ressetterr = Y.one("#resetit");
Y.one(ressetterr).on("click", function(e){
console.log("resetit");
e.preventDefault();
});
I have an autocomplete widget which needs to return options from a database of objects.
On doing so, once the user selects an item the widget will populate other hidden textfields with values from the particular object they chose. - All of this works and has been used on previous projects
However this particular database is far too big (44k+ objects, filesize is several mb and has taken far too long to load in practice) so we've tried various ways of splitting it up. So far the best has been by first letter of the object label.
As a result I'm trying to create a function which tracks the users input into a textfield and returns the first letter. This is then used to AJAX a file of that name (e.g. a.js).
That said I've never had much luck trying to track user input at this level and normally find that it takes a couple keystrokes for everything to get working when I'm trying to get it done on the first keystroke. Does anyone have any advice on a better way of going about this objective? Or why the process doesn't work straight away?
Here is my current non-working code to track the user input - it's used on page load:
function startupp(){
console.log("starting");
$("#_Q0_Q0_Q0").on("keyup", function(){
console.log("further starting!");
if($("#_Q0_Q0_Q0").val().length == 1){
console.log("more starting");
countryChange(($("#_Q0_Q0_Q0").val()[0]).toUpperCase());
}
else{
console.log("over or under");
}
});
}
And an example of the data (dummy values):
tags=[
{
label:"label",
code:"1",
refnum:"555555",
la:"888",
DCSF:"4444",
type:"Not applicable",
status:"Open",
UR:"1",
gRegion:"North West"
},
....
];
edit: fixes applied:
Changed startupp from .change(function) to .on("keyup", function) - keydown could also be used, this is personal preference for me.
Changed the autocomplete settings to have minLength: 4, - as the data starts loading from the first letter this gives it the few extra split ms to load the data before offering options and also cuts down how much data needs to be shown (helps for a couple of specific instances).
Changed how the source is gathered by changing the autocomplete setting to the following:
source: function(request, response) {
var results = $.ui.autocomplete.filter(tags, request.term);
response(results.slice(0, 20));
},
where tags is the array with the data.
all seems to be working now.
You should bind to keydown event:
function startupp(){
console.log("starting");
$("#_Q0_Q0_Q0").keydown(function(){
console.log("further starting!");
if($(this).length() == 1){
console.log("more starting");
countryChange(($(this).val()[0]).toUpperCase());
}
else{
console.log("over or under");
}
});
}
I have written a small form with some calculations. Now the calculation are done using button click event.
$('a#check_var').click(function() {
// the below call the form validation
$("#bet_cal_form").valid();
<- My code here ->
});
Now everything works, problems is I don't want my code to execute unless there are no error in the form validation. Currently I get the error messages but also my code get executed.
Use an if statement, of course.
if ($("#bet_cal_form").valid()) {
// Stuff that should only be done if form is valid
}
You need an if and to cancel the link and since all IDs need to be unique, you do not need the a in the selector
$(function() {
$("#check_var").on("click",function(e) {
e.preventDefault();
// the below call the form validation
if($("#bet_cal_form").valid()) {
<- My code here ->
}
});
});
Hope you can assist.
I am currently trying to conduct one of the most simplest tasks via a user event script - that is to set a new value in the 'discount rate' field on the sales order. My script works fine when testing it on the client, but when the scheduled script is triggered, the field fails to set/update.
The following code is within a 'beforesubmit' operation. Can you spot what I have done wrong?
function beforeSubmit_discountVAT(type){
if(nlapiGetContext().getExecutionContext() !='scheduled')
return;
var getDiscountVal = nlapiGetFieldValue('discountrate');
var correctDiscount = getDiscountVal / 1.2;
nlapiSetFieldValue('discountrate', correctDiscount);
}
In short - All i want to do is deduct the discount value by 20%. Can you use 'nlapiSetFieldValue' when a user event script is triggered from a scheduled script?
Thanks in advance.
AWB
When editing an existing record, nlapiSetFieldValue cannot be used in a Before Load event on fields that are stored with the record. From the function's JSDocs:
Sets the value of a given body field. This API can be used in user event beforeLoad scripts to initialize field on new records or non-stored fields.
nlapiSetFieldValue can thus only be used reliably in Before Load on new records or non-stored fields.
Realizing this is a month old so you've probably found a solution, I would move your code to the Before Submit event. I tested this using a Scheduled Script:
var customer = nlapiLoadRecord('customer', '31294');
nlapiSubmitRecord(customer);
and User Event on the Customer record, Before Submit event:
if (nlapiGetContext().getExecutionContext() === 'scheduled') {
nlapiSetFieldValue('url', 'http://www.google.com/', false);
}
This works as expected for me in a 2013.1 Sandbox environment.
Using nlapiSubmitField in After Submit as mentioned in the other answer is an unnecessarily long operation that will use extra governance units. Not a huge deal if that's the only thing your script is doing, but if you ever expand the script or add looping, it can add up quickly in terms of performance and governance usage.
Also, it may not be necessary, but you should ensure that getDiscountVal is a Number by doing:
var getDiscountVal = parseInt(nlapiGetFieldValue('discountrate'), 10);
If it comes back as a String then your division operation may give a strange result which may also cause nlapiSetFieldValue to fail or set the field to an odd value.
two suggestions
Make sure that your script is being executed by adding a few nlapiLogExecution statements
Instead of doing it in beforesubmit, change this field in aftersubmit function using nlapiSubmitField
"Can you use 'nlapiSetFieldValue' when a user event script is triggered from a scheduled script?"
Yeah Absolutely yes.Context is also correct its scheduled.
Please make sure that you are submitting the record nlapiSubmitRecord(recordObj) at the end.
If you are not comfortable with nlapiSubmitRecord() you can obviously use nlapiSubmitField()
If still you get stuck up then please paste the complete code so that we could assist you.
Cheers!!!