ExtJS ComboBox validation returns unexpected result - javascript

I've just been working on a ExtJS script and I have a ComboBox which has
allowBlank = false
and
forceSelection = true
I have an item in the list which acts as a default message which has a display text
Please select...
and no value
''
When I run validate on the ComboBox I get true
No idea why?
According to the documentation when
allowBlank = false
the validation is forced to check for value.length > 0
So I have done my own test in the JS Console
>> if (thisForm.controlManager.controlArray[2].allowBlanks) { if (thisForm.controlManager.controlArray[2].length >= 0) { true; } false; } else { if (thisForm.controlManager.controlArray[2].length > 0) { true; } false; }
and it returned false
So I thought it might a bug in validate method so I tried doing this
>> thisForm.controlManager.controlArray[2].validateValue('')
and got this as a result true
Any one have any kind of idea of what I might be doing wrong or if anything else needs set to get this validate to return false when value is ''.
PS. I've also tried this
>> thisForm.controlManager.controlArray[2].validateValue(' ')
and got the correct result which is false. This made me very confused as I would normally expect '' and ' ' to return the same value in validation.
I know that a workaround would be to set my value to ' ' but I would rather get it working with ''.
Thanks

I just so happened to end up grappling with this same issue, and after some looking around, managed to find a solution which does not require overriding Extjs's standard functionality.
Basically, there is a 'validator' config option for descendents of Ext.form.field.Text which allows programmers to specify a custom validation function for a component (see here).
Basically, your validator function gets called at the start of getErrors() and is evaluated before the rest of the field's standard validation. The validator function takes one argument (the value) and must return either true if the value is valid or an error message string if it is not.
The following config ended up working for my case:
validator: function (value) {
return (value === '/*Your emptytext text*/') ? "blankText" : true;
}

You have to use the emptyText configuration
Ext have this code for validate fields:
validate : function(){
if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
this.clearInvalid();
return true;
}
return false;
}
and getRawValue is defined like this:
getRawValue : function(){
var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
if(v === this.emptyText){
v = '';
}
return v;
}
so, if the value is equal to the empty text, the returned value is ''

Related

Refactoring validation handling and messaging

I am working on a react project that uses redux forms. I've looped through the fields to check their validation requirements if need be. This stack works well - but I know I should re-visit this to place parts inside a function
if(field.validate.includes("email")) {
//email
if (!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values[fieldName])) {
errors[fieldName] = 'Invalid email address'
}
}
if(field.validate.includes("minLength")) {
//minLength
if (values[fieldName] !== undefined && values[fieldName].length < 3) {
errors[fieldName] = 'Must be 3 characters or more'
}
}
if(field.validate.includes("required")) {
//required
if (!values[fieldName] && typeof values[fieldName] !== "number") {
errors[fieldName] = 'Required'
}
}
I've tried to write a function that looks like this - but I don't want to break the stack.
messageHandler(field, validation, rule, message){
if(field.validate.includes(validation)) {
if (rule) {
return message;
}
}
}
From what I can see, you're trying to validate a field's content against a set of defined rules.
To me, rules are just functions that can either be successful or not. For the sake of simplicity, let's say that if they return null it means that they are successful and otherwise, we'll return an error message (just a string).
const rules = {
email: value => !/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)
? 'Invalid email address'
: null,
minLength: value => value !== undefined && value.length < 3
? 'Must be 3 characters or more'
: null,
required: value => !value && typeof value !== "number"
? 'Required'
: null,
};
Now, for each rule that we find in field.validate, we'll apply the corresponding rule and collect the result :
const matchingRules = field.validate
.map(formValidate => rules[formValidate])
.filter(x => x); // filter nullish values (rules that are not found)
const errors = matchingRules
.map(fn => fn(values[fieldName]))
.filter(x => x); // filter nullish values (successful rules)
Now, errors contains a list of strings describing how the field failed the different rules, and of course, if errors.length === 0, the test is successful.
You can add as many rules as you want without repeating all the ifs.
Is it acceptable in this project to bring in another lib? I like to use joi for validation. Of course, it is important to understand how validation works under the hood, but it seems like you have a pretty good grasp on that.
Here's an example of how you'd implement this with your current code:
First you would define a schema, which essentially represents your ideal end-state for your filled-in form. Below, I am saying that the form values will include an email, which will be a required string that is at least 3 characters long.
const Joi = require('joi');
const schema = Joi.object({
email: Joi.string().email().required().min(3)
})
Then, when you are ready to validate the form data:
const validation = schema.validate({ email: 'foo#bar.com' });
validation will contain values & errors (if there are any).
You can throw that schema.validate function in a useEffect that fires off whenever the user updates an input, or you can wait until the user is trying to submit the form, whatever your UI requires.
I like it because it is easy to read and write and it's quite flexible.

IF condition using string

I am programming in Polymer 1.0 and am trying to create an IF function to change the value of a property. My function is the following:
_searchButton: function(selectednamedropdown, selectedtypedropdown){
if (selectednamedropdown=="no_name_selected" && selectedtypedropdown=="no_type_selected"){
this.searchUsagesBtn = true
} else{
this.searchUsagesBtn = false
}
}
In my mind when selectednamedropdown is equal to "no_name_selected" and selectedtypedropdown is equal to "no_type_selected" the function should set searchUsagesBtn to true and when they are not these values, false.
However, the function does not ever seem to be returning true even when these conditions are met. Any ideas why this might be? Thanks for all help
When I run your function like this:
let searchUsagesBtn;
function search(selectednamedropdown, selectedtypedropdown) {
if (
selectednamedropdown === "no_name_selected" &&
selectedtypedropdown === "no_type_selected"
) {
searchUsagesBtn = true;
} else {
searchUsagesBtn = false;
}
}
search("no_name_selected", "no_type_selected");
console.log("button: ", searchUsagesBtn);
I get button: true in console log. So maybe your inputs in this function are not a strings.
The issue was around how JavaScript treats properties within functions. The function was storing the new value and old value of the first property and not any values of the second property. The solution involved making 2 functions to test the strings in each property. Thanks for all assistance

How to filter out usercreated events in fullcalendar

I have a fullcalendar where I display non-editable events which are collected from a google calendar, or from a database. Then I want to register customer requests for events from the calendar. This works, but I am not able to list only the events that are added by the user.
Any hint on how to do this?
I tried this:
function retrieve_events() {
var rdv=$('#calendar').fullCalendar( 'clientEvents', undefined);
for (i=0; i<=rdv.length-1; i++) {
/*alert(rdv.toSource());*/
alert(rdv[i].title+" id: "+rdv[i].id+" start: "+rdv[i].start+" end:"+rdv[i].end+" heldag:"+rdv[i].allDay);
}
}
The the "undefined" as id, means that I have given all the non-editable events an id, while the new ones haven't got one. But this way I get all events listed, even those without an id. The same happens with null and ''. But using hardcoded id-numbers returns that specific event.
I see from the documentation that there seems to be other ways to get hold of the events I need, by using other criteria like classes. However I cannot figure out how to specify this filter.
I haven't worked with FullCalendar yet nor do I intend to extensively test this, so I cannot guarantee that this will work.
However, why don't you simple test whether rdv[i].id evaluates to false?
Try:
function retrieve_events( ) {
var rdv = $('#calendar').fullCalendar('clientEvents'),
results = [];
for( var i = 0; i < rdv.length; ++i ) {
if( !rdv[i].id ) {
results.push(rdv[i]);
}
}
return results;
}
P.S.: Passing undefined to .fullCalendar() probably is redundant. It would be equivalent to passing only a single variable. I'd guess the second parameter is a type of events that you can filter for, but passing only a single parameter would cause the plugin to return all events. Also, note that !!'' === false.
The internal check whether the second parameter is set is probably similar to this:
$.fn.fullCalendar = function( command ) {
switch( command ) {
// ... some case's
case 'clientEvents':
var filter = arguments[1];
if( !filter ) {
// Retrieve ALL client events
}
else {
// Filter client events
}
break;
// ... some more case's
}
};
This does not compare types. Testing filter === false would only return true, if filter would evaluate to false and is a boolean.
Following are examples of values that evaluate to false. There may be more, but I believe those are all.
undefined
null
0
false
''

Javascript populate form after validation

I am doing a form for my javascript class, and I am getting stuck on a certain portion of it. I have a separate validator javascript file and call the function on the html file. All the validation works if the form areas are not filled in. What I want to do is if the fields are left blank they will fail the validation and will insert a value into that field. Below are an example of the form field, javascript function in the html page, and the external validator js file.
call function in html head:
function formvalidation(thisform) {
with (thisform) {
if (textbox_validation(first_name,"Please enter your first name.")==false)
{first_name.blur(); return false;};
if (textbox_validation(business_name,"Please enter your business. Please enter N/A if
you do not have one.")==false) { business_name.focus(); return false;
business_name.value=="N/A";};
The external js validator:
function textbox_validation(entered, alertbox) {
with (entered) {
if (value==null || value=="") {
alert(alertbox);
return false;
}
else {
return true;
}
}
}
So the validator works and focuses on the empty fields, but for some of my fields I want them to fill themselves with a certain value if validation fails or if it isnt filled int. The business_name line of code is when I tried to make it work. Any help is much appreciated!
Ordinarilly, you wouldn't use alert, but would instead put error messages in a span or div either near the input or at the top (or bottom) of the form. Additionally (as mentioned by #Frits van Campen) it is generally bad practice to use with
Try something like this instead:
function textbox_validation(entered, errormsg) {
var errbox = document.getElementById(entered.id + '-errors'); // just to prevent writing it twice
// Note this requires the input to have an id, and the errer box's id to be the same with an '-errors' suffix.
// Instead of using with, just acces properties normally
if (!entered.value) { // The `!` "neggation" operater makes "falsy" values `true`
// "falsy" values include `false`, the empty string, `0`, `null`, `undefined`, `NaN` and a few others
// Put the error message in the DOM instead of alerting it
errbox.innerHTML = errormsg;
return false;
}
else {
// Wipe any previous error messages
errbox.innerHTML = '';
return true;
}
}
And for the form validator, again; let's not use with. But also, when attempting to assing "N/A" to the value, you've used the comparison operator instead of the assignment operator, and you've done it after returning:
function formvalidation(thisform) {
// just use the `!` "negation" operator
if (!textbox_validation(thisform.first_name,
"Please enter your first name."))
{
thisform.first_name.blur();
return false;
}
if (!textbox_validation(business_name,
"Please enter your business. Please enter N/A if you do not have one."))
{
thisform.business_name.focus();
thisform.business_name.value = "N/A"; // for assignment, use `=`. `==` and `===` are used for comparison
return false; // a return statement ends the function, make sure it's after anything you want to execute!
}
}
Use the DOM to set the placeholder for the fields. Like this.
var myInput = document.getElementById('input1');
myInput.placeholder = 'This validation has failed.';

lack of identity between jQuery selector and jQuery variable?

I'm running into a maddening problem where I set a variable to point to a jQuery selector, such as: var foobar=jQuery(this); I then pass this variable to a function to be worked on. Let's simplify a little and say the function looks like this:
function SetFieldValue (selector) {
selector.val('test');
console.log ( selector );
console.log ( jQuery('#' + selector.attr('id')) );
}
In this situation if you assume that:
the selector is always a form element (and therefore val() is a valid operation)
the selector does resolve to a single dom element which has an 'id' attribute
You would then expect the two console.log statements to output the same result, right? Well I'm running into a situation where this condition only happens about 90% of the time.
In order to give more context I've created a short screencast demonstrating the problem:
SCREENCAST LINK
For reference purposes, here's the actual SetFieldValue code that is shown in the screencast:
function SetFieldValue ( domObject, value ) {
// as a safety function, check if a string representation of the domObject was passed in and convert it to a jQuery object if it was
if ( jQuery.type(domObject) === "string") {
console.log ("Value passed into SetFieldValue was a string representation so converting to jQuery object");
domObject = jQuery(domObject);
}
if ( jQuery.inArray (domObject.prop('tagName').toLowerCase(),['input' , 'select' , 'textarea']) >= 0 ) {
console.log ("setting to value attribute: " + value);
if ( domObject.hasAttr('id') ) {
domObject.val(value);
//jQuery('#' + domObject.attr('id')).val(value);
} else {
domObject.attr('value',value);
}
console.log ("Using jQuery ID it is set to: " + jQuery('#' + domObject.attr('id')).val() );
console.log ("Using jQuery selector variable it is set to: " + domObject.val() );
} else {
console.log ("setting to html attribute");
domObject.html( value );
}
return domObject;
}
Lets examine the code a bit.
First assigning back to a parameter is not a good practice adding a var at the start of your function would be a lot better, as scope can be lost.
//Suggestion change parameter to domItem
var domObject
Your missing an error handler for when the parameter is not String.
when identifying the type use
<VARNAME>.constructor.toString().match(/function (\w*)/)[1] === "<TYPE>"
It's more efficient and handles custom types.
No need for all the logic in assignment of value attribute. Any dom Object can be made to have a value attribute. also not sure why you are setting the val versus the value.
domObject.attr('value',value);
It is at this point that I can see your code could really use some documentation to help explain purpose
If you are explicitly only wanting to set value on Input fields and set value as innerhtml on non input fields then yes the logic would be needed but could be simplified to ... as the value doesn't need to be detected to overwritten.
if (jQuery.inArray (domObject.prop('tagName').toLowerCase(), ['input' , 'select' , 'textarea']) >= 0) {
domObject.attr('value',value);
} else {
domObject.html( value );
}
No Idea why you are returning the domObject out.
So a quick rewrite without the return and keeping most of the logic adding error handling results in
/*jslint sloppy: true*/
/*global jQuery*/
function SetFieldValue(domString, value) {
// as a safety function, check if a string representation of the domObjects was passed in and convert it to a jQuery object if it was
var domObjects, index;
//errorhandling
if (domString === undefined || domString === null) {
throw {error : "domString must have a value."};
}
if (domString.constructor.toString().match(/function (\w*)/)[1] !== "string") {
if (domString.constructor.toString().match(/function (\w*)/)[1].match(/HTML[a-zA-Z]*Element/) === null) {
throw {error : "domString expected to be String or domObjects"};
}
} else {
if (jQuery(domString).length === 0) {
throw {error : "domString does not resolve to a detectable domObjects."};
}
}
//errorhandling
//action
if (domString.constructor.toString().match(/function (\w*)/)[1].match(/HTML[a-zA-Z]*Element/)) {
//made as an array to normalize as jQuery returns an array allows code to be simplified
domObjects = [domString];
} else {
domObjects = jQuery(domString);
}
//given that domObjects are an array need to step through the array
for (index = domObjects.length - 1; index >= 0; index -= 1) {
if (
jQuery.inArray(
domObjects[index].tagName.toLowerCase(),
['input', 'select', 'textarea']
) >= 0
) {
if (domObjects[index].hasAttr('id')) {
domObjects[index].val(value);
} else {
domObjects[index].attr('value', value);
}
} else {
domObjects[index].html(value);
}
}
}
The above passes JSLint
I know I didn't provide enough context for people to really dig into this problem but I have in the end solved it. What was the issue? Well it was #Kobi who first asked is the DOM element's ID unique ... to which I happily reported it was. And it had been but in fact that WAS the problem. Jesus. It's always the obvious things that you then go onto overlook that get you in trouble.
Anyway, thanks for your patience and help.

Categories

Resources