Custom Unobtrusive Validation Method Not Firing as Per Documentation - javascript

I've been attempting to implement a ASP.NET MVC custom validation method. Tutorials I've used such as codeproject explain that you add data-val-customname to the element. Then jQuery.validate.unobtrusive.js then uses the third segment of the attribute
data-val-<customname>
as the name of the rule, as shown below.
$.validator.addMethod('customname', function(value, element, param) {
//... return true or false
});
However I just can't get the customname method to fire. By playing around I have been able to get the below code to work, but according to all the sources I've read Unobtrusive validation should not work like this.
$.validator.addMethod('data-val-customname', function(value, element, param) {
//... return true or false
});
I've posted an example of both methods
jsfiddle example
Any help would be much appreciated
I've updated my question hopefully to make clearer.

I have finally found got there in the end, but still feels like too much hard work and therefore I've probably got something wrong. Initial I was scuppered by a bug in Chrome Canary 62 which refused to allow the adding of a custom method.
My next issue was having to load jQuery, jQuery.validate and jQuery.validate.unobtrusive in the markup and then isolate javascript implementation in a ES6 class. I didn't want to add my adaptors before $().ready() because of my class structure and loading of the app file independent of jQuery. So I had to force $.validator.unobtrusive.parse(document);.
Despite this I was still having issues and finally debugged the source code and found that an existing validator information that is attached to the form was not merging with the updated parsed rules, and essentially ignoring any new adaptors added.
My final work around and admit feels like I've done too much, was to destroy the initial validation information before my forced re-parse.
Here is the working jsfiddle demo
Here is some simplified code
onJQueryReady() {
let formValidator = $.data(document.querySelector('form'), "validator" );
formValidator.destroy();
$.validator.unobtrusive.adapters.add("telephone", [], function (options) {
options.rules['telephone'] = {};
options.messages['telephone'] = options.message;
});
$.validator.unobtrusive.parse(document);
$.validator.addMethod("telephone", this.handleValidateTelephoneNumber);
}

Related

How to deal with DOM elements?

I am learning about writing custom JavaScript for my Odoo 10 addons.
I've written the following piece of code:
odoo.define('ioio.io', function(require) {
'use strict'
const e = $('div.o_sub_menu_footer')
console.log('--testing--'.repeat(7))
console.log(e)
// the "Powered by Odoo" down the secondary menu
e.remove()
})
The code is well loaded and I can see my testing string in the console.
However when this code is being loaded before the target div, so e empty/not yet filled and thus its content is not removed.
Doing it manually from the console works.
My question is what is the right way to do that? And how to know exactly when the code gets executed?
You can
put your html code before the script tag in your file
use jQuery $(document).ready(...);
Place your script at the bottom of the <body> tag to make sure the DOM renders before trying to manipulate it.
This is an Odoo specific question, so you should use the Odoo standard way, which is via its base JS class. That class contains a ready() method which does exactly what you need.
In your case, to use that function, you need to require the class first. Then you can use ready().
Updating your code, it should look like this:
odoo.define('ioio.io', function(require) {
'use strict'
// require base class
var base = require('web_editor.base');
//use its ready method
base.ready().done(function () {
// put all the code you want to get loaded
// once the DOM is loaded within this block
const e = $('div.o_sub_menu_footer')
console.log('--testing--'.repeat(7))
console.log(e)
// the "Powered by Odoo" down the secondary menu
e.remove()
});
})
While your accepted answer leads to the same outcome, you might want to update it to this one since this is the Odoo way. It's generally advised to work within the Odoo framework as much as possible and customise only if really needed. (Though it can be tough to learn what features Odoo already provides because of its poor documentation.)

Validate function works on ValidationTextBox but not on FilteringSelect. Why?

I'm having a rather strange behaviour and don't know if it's because something I'm not doing right.
I trying to customize a Dojo FilteringSelect in my application to show invalid messages at my will. Looking at the API, I found a way to do it. This way works fine for ValidationTextBox.
Code to switch validation state:
var originalValidator = textBox.validator;
textBox.validator = function() {return false;}
textBox.validate();
textBox.validator = originalValidator;
Here's a fiddle so you can take a look:
http://jsfiddle.net/phusick/HGBnq/
If I change the ValidationTextBox to a FilteringSelect, it should work the same. But for some reason, it doesn't!
Here's the fiddle:
http://jsfiddle.net/nachoargentina/HGBnq/421/
Any suggestions are greatly appreciated!
dijit/form/FilteringSelect does indeed inherit from dijit/form/ValidationTextBox, but it overrides isValid (source). isValid is what calls the validator function in ValidationTexBox.
You could compose your own FilteringSelect that uses the same method that ValidationTextBox uses for isValid, or whatever you wanted or needed to use.

Querying the DOM in Windows 8 Apps from within a method

I'm struggling with this even after reading the MSDN documentation and the following online guides:
Codefoster
Stephen Walter
I think my problem is easy to fix and that I just am thinking about something in the wrong way. Basically I am querying my web service and on success running the following method. I am then trying to bind the result to my listview. For now I am using a hardcoded value publicMembers.itemlistwhich has been declared at the top of the document just to make sure I can actually bind to the list before doing it with my query results. Ignore line 2 for now.
Success Method:
_lookUpSuccess: function xhrSucceed(Result) {
var response = JSON.parse(Result.responseText);
listView = document.querySelector("#termTest");
ui.setOptions(listView, {
itemDataSource: publicMembers.itemList,
itemTemplate: document.querySelector(".itemtemplate"),
})
},
Now, instead of using document.querySelector, I have also tried with WinJS.Utilities.id and WinJS.Utilities.query, neither of which worked either. This doesn't break my code and introduce an error but it doesn't bind to the listview either so I think I have an issue in querying the right DOM element. However exactly the same code does work if I add it to the top of the script, it is only when I place it in this method that it stops working.
EDIT: Also to clarify, when I debug publicMembers.itemList is storing the values I expect them to be.
Please point out if I have explained things poorly and I will try and improve my question.
Thanks.
I haven't used WinJS.UI.setOptions, but rather this other way of setting the data source. Can you see if it works?
_lookUpSuccess: function xhrSucceed(result) {
var response = JSON.parse(result.responseText);
listView = document.querySelector("#termTest");
listView.winControl.itemDataSource = publicMembers.itemList;
},
This would assume you're defining the itemTemplate as part of the data-win-options attribute of your ListView's HTML element. You could also probably just do listView.winControl.itemTemplate = document.querySelector(".itemtemplate") if you prefer to set it programmatically.

"Error calling method on NPObject!" in Uploadify

I'm using Uploadify to upload file in my CMS. Everything works fine until recently. I got an error
Error calling method on NPObject
on this line
document.getElementById(jQuery(this).attr('id') + 'Uploader').startFileUpload(ID, checkComplete);
on this part
uploadifyUpload:function(ID,checkComplete) {
jQuery(this).each(function() {
if (!checkComplete) checkComplete = false;
document.getElementById(jQuery(this).attr('id') + 'Uploader').startFileUpload(ID, checkComplete);
});
},
I don't know why and after a day debugging and testing I found that if I remove replace(/\&/g, '\\&') from
String.prototype.escAll = function(){
var s = this;
return s.replace(/\./g, '\\.').replace(/\?/g, '\\?').replace(/\&/g, '\\&');
};
It then works again. I really don't know why.
Any helps would be appreciated!
I think the reason is in additional Javascript libraries you use.
Some libraries (for example Prototype.js or jQuery.js) change behaviour of your code. For example, you can't overload prototype in some cases. The result may be undefined in clear (obvious) places (like you use an array variable with wrong index). You should view the source code of additional libraries, probably they do with prototype something that breaks your code in the function you mentioned.
In my practice I had the situation when overloading of prototype worked incorrectly (it was String prototype like in your case).
So just don't use prototype.

Prototype: call custom function after validation

I'm using prototype and needs to call my function after succesfull validation.
Part of the code:
var validator = new Validation(this.form);
this will validate the form, but I don't know how to call my function trackForm after the validation is correct and the form is submited.
Any help?
I would need more details to answer, at least will try then.
I assume you're using PrototypeJS - the library. This lib does not support validation by default so you're probably using another library for that.
If you're using Dexagogo's validation (http://tetlaw.id.au/view/javascript/really-easy-field-validation) you will need to use onFormValidate callback.
I never used it, but presume you basically setup Validation like normally, with addition of that extra attribute. Like this:
var validator = new Validator(this.form, {onFormValidate: trackForm});
var trackForm = function (validationPassed, form) {
if (validationPassed) {
form.reset();
}
}
Ofc you don't need to create trackForm, but written as you mentioned about it.
Hope this somewhat helps.
I appreciate that the original question didn't mention the platform, but I found this question after Googling extensively for a solution on the Magento platform.
For those using Prototype through Magento and Magento's VarienForm, there's a simple way to do with without using any other validation libraries.
The validator is attached to the form when its initialised, and the onFormValidate method is an option on the validator.
You can access is as below:
this.form.validator.options.onFormValidate = function(validationPassed, form) {};
See the below example which I have tested for my own means and found it works exactly as expected:
var contactForm = new VarienForm('contactForm', true);
contactForm.validator.options.onFormValidate = function(validationPassed, form) {
if(validationPassed){
alert("Validation Passed");
}
}

Categories

Resources