In .NET 2.0, I have several client side validators ala the .NET validator controls. These run fine when I click a button...until I add my own javascript function to this button. Instead of running in addtion to the validators, it seems to prevent them from running at all.
To be clear, the validator controls are basic required field validators, and here is the javascript I added:
<script language="javascript">
function yaya()
{
var chkAmount = document.frmSearchFor.txtCheckAmount.value;
var amtApplied = document.frmSearchFor.lblAmountApplied.value;
if (amtApplied < chkAmount)
{
return confirm('Continue?');
}
}
</script>
And it's tied to the button like this...
OnClientClick="return yaya();
those are probably not the ID's being rendered to your page. Try this:
function yaya()
{
var checkAmount = parseFloat(document.getElementById("<%=txtCheckAmount.ClientID %>").value);
var amoutApplied = parseFloat(document.getElementById("<%=lblAmountApplied.ClientID %>").text);
if (amoutApplied < checkAmount)
{
return confirm('Continue?');
}
}
And try attaching it like this:
OnClientClick="javascript:yaya();";
Client-side validation is done via javascript just like your client click. When you specify the client-side event, I'm guessing there's nowhere for the validation code to attach. You may need to modify either the validation code to call your function, or your function to call the validation code. Probably the latter is easier. Instead of assigning OnClientClick at design time, add a client script that stores the current click handler function, creates a function that runs your code and then runs the stored handler function, and attaches that new function as the click handler.
<script>
var baseHandler = myElement.onclick;
myElement.onClick = function() {
// run your code here
baseHandler();
}
</script>
issue is that you are specifying a return in your OnClientClick attribute. when the page renders, it comes out like this
<input ... onclick="return yaya();WebForm_DoPostBackWithOptions...
after yaya completes, the onclick function concludes and I believe it's shutting down any further action that would normally happen before the form is submitted. it's kind of ugly but you can get around this by only having a return when your function evaluates to false:
OnClientClick="if (!yaya()) { return false; }"
for this to work you should also include return true; at the end of your function in case the conditions for the if check are not met.
you may also be having issues with references to elements as Hunter mentions but you're not providing your markup to verify that.
Related
I have the following buttons:
<button id="abcd" onclick="something()">click</button>
and the following functions are attached to this button apart from the one in its html definition.
$('#abcd').on('click',function(){alert("abcd");});
$('#abcd').on('click',function(){
someAjaxCallWithCallback;
});
Now I want a new function with another ajax call to execute on this button's click, before the above mentioned functions. This new function determines whether the remaining functions would be called or not based on what data is recieved by the ajax call. That is, this pre function should complete its execution before giving control over to the rest of the functions and also determine whether they would run or not.
As an example, without changing the existing validation logics and button code, I have to add a new pre-validation function and similarly and post validation function.
I have a bindFirst method using which I can at least bring my new function to the beginning of the call stack but I have not been able to contain its execution and control further delegation because of callbacks.
If I understand correctly, you are looking for the way to do this, without modifying html and already existing js, only by adding new js-code.
First of all, if onclick handler is set and you want to control it, you should disable it on page load (maybe, saving it to some variable):
$(document).ready(function() {
var onclick = $("#abcd").attr("onclick").split("(")[0];
//to run it in future: window[onclick]();
$("#abcd").attr("onclick", "");
});
Edit: I changed my answer a little, previous approach didn't work.
Now you need to remove all already existing handlers. If number of handlers you want to control is limited, constant and known to you, you can simply call them in if-else after pre-validation inside your pre-function. If you want something more flexible, you are able to get all the handlers before removing, save them and then call them in a loop.
For that "flexible" solution in the end of $(document).ready(); you save all already existing handlers to an array and disable them. Then you write your pre-function and leave it as the only handler.
var handlers = ($._data($("#abcd")[0], "events")["click"]).slice();
$("#abcd").off("click");
$("#abcd").click(function() {
//this is your pre-func
//some code
handlers[1].handler.call();
});
Try console.log($._data($("#abcd")[0], "events")) to see, what it is.
Finally just run your post-function and do whatever you need, using conditions.
So, the general algorithm is as follows:
Disable onclick
Save all handlers
Disable all handlers
Run pre-func first
Run handlers you want to be executed
Run post-func
In fact, you just make your pre-func the only handler, which can run all other handlers you may need.
Although Alex was spot on, I just wanted to add more details to cover certain cases that were left open.
class preClass{
constructor(name,id){
if($(id) && $(id)[0] && $(id)[0]['on'+name])
{
var existing = $(id)[0]['on'+name]
$(id).bindFirst(name,existing);
$(id).removeAttr('on'+name)
alert("here");
}
if($._data($(id)[0],"events")){
this.handlers = $._data($(id)[0],"events")[name].slice();
}
else
{
this.handlers = null;
}
this.id = id;
this.name = name;
}
generatePreMethod(fn,data)
{
$(this.id).off(this.name);
$(this.id).bindFirst(this.name,function(){
$.when(fn()).then(execAll(data));
});
}
}
function exec(item,index){
item.handler.call()
}
function execAll(handlers){
return function(){ handlers.forEach(exec);}
}
This more or less takes care of all the cases.
Please let me know if there is something I missed!
There is probably a really easy solution to this but I cannot for the life of me work out how to fix this issue, and nothing I have found so far has done the trick.
I'm trying to get the function "validate" to run when the form "apply" is submitted:
function init() {
var applyForm = document.getElementById("apply");
setJobValue();
applyForm.onsubmit = validate;
}
Validate looks like the following:
function validate() {
alert("If this alert is up then validate is running");
var dateOfBirth = document.getElementById("dob").value;
var state = document.getElementById("state").value;
var postcode = document.getElementById("postcode").value;
etc.
The function "setJobValue" is running (so I know init is working) and there are no errors in the console, but what adjustments would I have to make for validate to be called?
Well, what happens is that when you put your code above in the head, the script runs when the HTML gets rendered. So during that time, it allocates different memory and function blocks. So when you call that function again, then it gives you different results and no errors because of the existing references. Well its a bit weird but its the way JS works and it is always recommended to put your JS code at the bottom of the page.
You can directly call validate method from your init method instead.
function init() {
var applyForm = document.getElementById("apply");
setJobValue();
validate();
}
When we assign a function to an event, it will fire at last.
so in your case, This should work
function init() {
var applyForm = document.getElementById("apply");
setJobValue();
applyForm.onsubmit = functionToSave;
}
And call your validation method on the submit button onclick event.
I've got a web page that uses an UpdatePanel and validation within.
Because of requirements specified within, I have to display a custom model when validation fails and so far, I've only been able to do this by overriding the Page_ClientValidate client side function:
function Page_ClientValidate(validationGroup) {
Page_InvalidControlToBeFocused = null;
if (typeof(Page_Validators) == "undefined") {
return true;
}
var i;
for (i = 0; i < Page_Validators.length; i++) {
ValidatorValidate(Page_Validators[i], validationGroup, null);
}
ValidatorUpdateIsValid();
ValidationSummaryOnSubmit(validationGroup);
Page_BlockSubmit = !Page_IsValid;
if(!Page_IsValid)
{
displayError();
}
return Page_IsValid;
}
This works great, but I've noticed that when using it within an UpdatePanel, as soon as the UpdatePanel generates new content, it seems the ScriptResource.axd's containing the original Page_ClientValidate is downloaded again, thus overriding my override (if that makes any sense).
Now, it displays the errors beside the fields, but doesn't call my displayError function.
Any suggestions?
I've thought about possibly writing something to monitor the error span's to see if they become visible, but not sure if that's overkill at the moment.
Thanks
Gavin
Are you using $(document).ready(...)?
if so, try to use the pageLoad() of the client side
http://encosia.com/document-ready-and-pageload-are-not-the-same/
I wrote a jquery plugin for validating forms. It bounds itself to the $('element').Submit event to trigger the validation (the bind is inside the plugin). Somehow like this:
// pseudocode
jquery.rdy {
$('form').validate(); //binding the plugin
}
Inside of the validate plug I bind the validation to the submit
//pseudocode
[...]
$().submit(function () {
validating... //returning true/false
if (false) {
return false //prevent submit form
}
}
[...]
So and now my question is how can I bind (in other js scripts for example) other stuff to the submit but just if a validation is done.
so like this
$('form').submit(function () {
if (validate plugin was executed) {
//do stuff like check if validation was returning a true and now do something else
}
}
Hopefully I descriped it right ...my english is not the best but I tryed to be as concrete s possible (and i hope, pseudocode is a right approach as well)
// EDIT: make the problem more concrete:
I'm trying to figure out a way to solve the following problem: (its very out of the context but the problem is exactly there..)
I have a submit event which is doing something depending on some code triggered in a another decleration.
$('element').submit(function () {
if ($(this).hasClass('foo')) {
// do something
}
});
$('element').submit(function () {
$(this).addClass('foo');
});
And now the first function is doing nothing cause it has been triggered before the second one. Is there a clean way to solve this. Maybe I need a timeout event (even I hate them)?
If you are using jQuery.Validate (which it looks like you are with the .validate() syntax), you can just call the isValid() method:
if (validate plugin was executed) {
can then be
if ($('form').isValid()) {
You can bind more functions to the form element with custom names.
$('form').bind('after_validation',function(){ console.log('hello'); });
And trigger them in your submit form function when you need it:
$('form').trigger('after_validation');
http://api.jquery.com/trigger/
Update:
You cannot change the order of your bound submit events without removing them .unbind('submit') and re-applying in the correct order. What you can do is use custom binds (see above) and trigger them exactly when you need it - like.. inside the submit function.
$('form').submit(function () {
//run validation
$('form').trigger('validation');
//did it pass validation?
if($(this).data('invalid')){
console.log('did not pass validation');
return false;
}
//passed validation - submit the form
return true;
});
//add validation to the "form"
$('form').bind('validation',function () {
//do validation on form...
if(false){
$(this).data('invalid',true);
}
});
//add another validator to the form, etc.
$('form').bind('validation',func...
Im using .data() to store variables to the 'form' element so you can access them down the chain.
This is the basis of what you need and can be applied to a custom jquery plugin to form custom named functions. eg. $().validator().
http://docs.jquery.com/Plugins/Authoring
I have a Dojo SubmitButton with jsId="saveParamButtonWidget". I overrided its onClick method by putting:
saveParamButtonWidget.onClick = editParam
I defined the editParam() function like this:
function editParam(eventObj) {
dojo.stopEvent(eventObj);
// ...
}
dojo.stopEvent() is supposed to stop event bubbling and default processing. However, the browser will submit the form anyway. I also tried with the following:
function editParam(eventObj) {
eventObj.stopPropagation();
eventObj.preventDefault();
// ...
}
Same thing. The only way I've managed to prevent form submission is by returning "false" from the event handler:
function editParam(eventObj) {
// ...
return false;
}
Can someone tell me why the first two ways did not work? Thanks.
Okay, after doing some digging through the source, I believe I can answer your question definitively.
The reason dojo.stopEvent() doesn't work, but return false does, is entirely due to how dijit.form.Button is coded. If you're interested, it's time for a little field trip. Keep your hard hats on.
When a dijit.form.Button is clicked...
The button's _onButtonClick method is invoked. (This is hooked up in the template, to the special ondijitclick event which captures not only mouse click but also certain keypresses, for a11y purposes.)
The _onButtonClick method first invokes the _onClick method, which, presuming the button is not disabled (which it's not in this case), invokes and returns the result of the onClick method. This is of particular interest since it's the method you're overriding!
Coming back to _onButtonClick, if _onClick returned precisely false (e.g. if your onClick handler returned false), _onButtonClick immediately bails out. This is why returning false makes your code work as desired. But what happens if it doesn't bail out there? Let's follow the trail further...
Next, _onButtonClick checks whether this button not a descendant of an actual HTML form, but is a descendant of a widget with an _onSubmit method (duck-typing). I'm assuming that in your case it is inside a real form (dijit.form.Form counts), so we'll skip over this. (I am under the impression that this code path wouldn't actually end up submitting, whereas yours apparently does.)
One final condition is checked: if the button has a valueNode defined (it does), the click method of this node is invoked. Unfortunately, this produces an entirely new event object on an invisible input type="submit" node under your form, and thus anything you tried to tell the original event is rendered immaterial, and the form goes on to submit! This is why dojo.stopEvent did not work - this code in dijit.form.Button pays it absolutely no heed.
I cooked this up as a somewhat-limited proof of concept (be sure to open firebug/etc. to get the logs): http://jsfiddle.net/Bf5H8/
Perhaps this is something that should be logged as a bug, but I suppose the initial thought may have been that supporting the well-known return false mechanism would be enough.
All this being said, it's quite possible that overriding onSubmit of the form is more in-line with your interests than overriding the button's onClick anyway (as S.Jones suggested), but at least this should solve the mystery.
Interesting question. +1
I believe you have to use dojo.connect to connect your function to a DOM event to get access to those methods with an event object.
See: The Event Object (DojoTollkit.org Reference Guide)
The Event Object
When you connect a function to a DOM
event with dojo.connect,
Dojo passes your function a normalized
event object. This means that,
regardless of the client's browser,
you can count on a set of standard
attributes about the event and a set
of methods to manipulate the event.
Assume that your function has been
called by dojo.connect and takes an
argument named event, like:
dojo.connect(dojo.byId("node"), "onclick", function(event){
// the var 'event' is available, and is the normalized object
});
...
Dojo normalizes the following methods with an event object:
event.preventDefault — prevent an event's default behavior (e.g., a link from loading a new page)
event.stopPropagation — prevent an event from triggering a parent node's event
Additionally, dojo.stopEvent(event)
will prevent both default behavior any
any propagation (bubbling) of an
event.
That said, placing a function like the one below in your form to perform some logic before submitting it, is a fairly clean, easily understood & maintainable approach.
<script type="dojo/method" event="onSubmit">
if (!this.validate()) { // or whatever else you'd like to evaluate
// insert calls here...
return false;
}
return true;
<script>
Cheers.
I had the same issue for using dojo.stopEvent
This issue is solved the form submission issue like this - here it is a simple form used to connect through dojo:
this.formId = dojo.byId("formId");
dojo.connect(this.formId, 'onsubmit', function(evt) {
var val_main = validate_this_form(0);
if(val_main == false)
dojo.stopEvent(evt);
});