Validating a linked field in Parsley.js - parsley.js

This question was asked by "jackrugile" on Github but I can't located the answer if it was ever given. I'm reposting here because having the exact same issue:
When using validation constraints that are linked to other fields (Equal To, Greater Than, Less Than, Before Date, After Date, etc.), whatever triggers a validation call on one field should automatically be called on the other. This is only applicable for triggers other than a submit (focusin, focusout, keydown, keyup, etc.)
For example, if I have a field called "Small Number" and a field called "Large Number", I would add the data-greaterthan attribute to the "Large Number" input to make sure it was larger. I then fill out the field as follows:
Small Number: 12
Large Number: 7
This validation obviously fails and an error shows up on on the "Large Number" field. Then, to fix this error, instead of making the "Large Number" larger than 12, I make the "Small Number" less than 7. The state of the form is now:
Small Number: 5
Large Number: 7
However, even though this should pass immediately because it is within the validation rules, it does not remove the error because no check was performed on "Large Number" again after changing "Small Number".
What is the best solution for this?

As far as I can tell, in Parsley 2.1 (current version), this is not supported. However, we can add the functionality by listening on the parsley events that are fired. I think there are a number of ways you could go about this. I have chosen to do it on field initialization. When a field is initialized, if it has a validator that depends on another field, I add a listener to that field, such that when that field changes, I re-execute my validation. Here is an example:
/**
* For fields that have a comparison to another field,
* setup a listener so that when one field changes, both
* fields re-validate.
*/
$.listen('parsley:field:init', function(e) {
var comparisonFields = ['gte', 'gt', 'lte', 'lt'];
for (var i = 0; i < comparisonFields.length; i++) {
if (e.OptionsFactory.fieldOptions[comparisonFields[i]]) {
$(e.OptionsFactory.fieldOptions[comparisonFields[i]]).on(e.OptionsFactory.staticOptions.trigger, function() {
$(e.$element).parsley().validate();
})
}
}
});
Note that if you add a listener on any init events, the code must come before you initialize your parsley form.

Related

split a number and populate N number of fields in react

for example if we take a number 100 and the user has three fields when user enters a number say 20 in one of the fields the other two fields should populate with the numbers 40 and 40 as 40+40+20 = 100. Unable to think of a logic which would help me solve this.This is just an example, the number of fields can be considered as N where N = 1,2,3,4 etc .
Seems straightforward, so I might be overlooking the point?
So, first we get whatever element the user interacted with. We could use either onChange, which will fire everytime the user changes the input, or onBlur which fires when the element loses focus, i.e. submits the form or selects the next input. Then we simply get the event.target.value, which in your presented case is 20.
Get the rest of the inputs by either storing a ref to their parent and getting said parents .children, or by using document.querySelectorAll(".some-selector"), iterate over the nodelist, skip any entry with a .value !== null and add 100 - 20 / (nodeList.length - 1) as the .value of the remaining entries.
I would probably use the ref route.

How best to store a number in google realtime model, and get atomic change events?

Sounds pretty simple, however...
This number holds an enumerated type, and should be a field within a custom realtime object. Here's its declaration in the custom object registration routine:
MyRTObjectType.prototype.myEnumeratedType =
gapi.drive.realtime.custom.collaborativeField('myEnumeratedType');
I can store it in the model as a simple javascript number, and initialize it like this:
function initializeMyRTObjectType() {
// other fields here
this.myEnumeratedType = 0;
}
...but the following doesn't work, of course, since it's just a number:
myRTObject.myEnumeratedType.addEventListener(
gapi.drive.realtime.EventType.OBJECT_CHANGED, self.onTypeChanged);
I can add the event listener to the whole object:
myRTObject.addEventListener(
gapi.drive.realtime.EventType.OBJECT_CHANGED, self.onTypeChanged);
But I'm only interested in changes to that number (and if I were interested in other changes, I wouldn't want to examine every field to see what's changed).
So let's say I store it as a realtime string, initializing it like this:
function initializeMyRTObjectType() {
var model = gapi.drive.realtime.custom.getModel(this);
// other fields here
this.myEnumeratedType = model.createString();
}
Now I'll get my change events, but they won't necessarily be atomic, and I can't know whether a change, say from "100" to "1001", is merely a change enroute to "101", and so whether I should react to it (this exact example may not be valid, but the idea is there...)
So the question is, is there either a way to know that all (compounded?) changes, insertions/deletions are complete on a string field, or (better) a different recommended way to store a number, and get atomic notification when it has been changed?
You also get a VALUE_CHANGED event on the containing object like you would for a map:
myRTObject.addEventListener(gapi.drive.realtime.EventType.VALUE_CHANGED,
function(event) {
if (event.property === 'myEnumeratedType') {
// business logic
}
});

Input[number] starting (not default) value

I'm trying to accomplish something that is a bit out of the ordinary. I have a regular <input type="number"> field with a designated min and max value where the user can input a year. When initially hitting the up or down arrow on the input field, the value starts at the min attribute's value. What I'm trying to accomplish is to get it to start at the max attribute's value.
Are there any straight-forward ways to accomplish this using either HTML or AngularJS? I could write some javascript to do it, but I would prefer to avoid that. Note that I don't want to default the field to that value on load, only when interacting with the control.
Note that the min and max values are determined at run-time from a table, so they can vary.

Password matching in AngularJS using the $validators pipeline produces unexpected results

See the example here.
Using the $validators pipeline, I am trying to check that a field contains the same value as another field.
Each input in this example is associated with the other, such that the expected result is as follows:
Enter a value in input#1
Enter same value in input#2
Both fields should now be valid
Alter the value in input#1
input#1 should be invalid (or input#2 or both)
Initially, I did this using a $watch on both the current model and the target to be equal to, so only one of the two fields needed to use the directive. However, with the introduction of the $validators pipeline, this method stopped working unexpectedly (maybe a bug).
Anyhow, as you can see, when the second input is altered, the value is receives for the associated input is undefined.
Solution
I solved this by the following:
JSFiddle
As Nikos said, the two instances were cancelling each other out, so this was fixed by the following code:
$scope.$watch('passwordWatch', function(pass) {
$control.$validate();
});
So now, when the target input changes, the current input revalidates. When the current input changes, it validates automatically (as usual).
One problem is that when a validator fails (returns false), then the underlying model value is set to undefined. So:
You type something in the password, say "aaa"; this is NOT the same as passwordConfirm, so the validator returns false and the model gets the undefined value
You type the same value in passwordConfirm; but from above the value of the password is undefined and undefined !== "aaa", so the passwordConfirm validator returns false too.
And so on...

xtype: numberfield value is going to auto correct(change) for more than 16 digit value

can any one explain why(how) the xtype: numberfield value is going to auto correct(change) if am providing more than a 16 digits value.
For Example:
22222222222222222 is changed to 22222222222222224
222222222222222222 is changed to 222222222222222200
2222222222222222222 is changed to 2222222222222222300
22222222222222222222 is changed to 22222222222222220000
222222222222222222222 is changed to 222222222222222230000
2222222222222222222222 is changed to 2.2222222222222222e+21
22222222222222222222222 is changed to 2.2222222222222223e+22
Which results in my page after rendering as shown below when get the value through in my component jsp page
NumberFieldTestValue:<%= properties.get("numberfieldname","") %>
Resulting as below
NumberFieldTestValue: 2.2222222222222223e+22
The problem
This behavior is caused by the fact that the dialog behavior is implemented in JavaScript. The numbers you're having problems with cannot be represented in it.
The language conforms to the ECMASCRIPT 5.1 specification.
To quote the Number type description
all the positive and negative integers whose magnitude is no greater
than 2^53 are representable in the Number type
The base 2 logarithm of 2222222222222222222222 is about 70, which means the number exceeds the maximum value. Hence your problems.
All in all, if you check your examples in a plain JS console in a browser, the same behavior will be displayed so this is not really a CQ problem.
Solution 1 - use a different type
To avoid this, you could potentially use xtype="textfield" and validate it against a regular expression to see if it consists of numbers only. Then you'd have to make sure to use a type capable of holding such numbers at the backend (like BigInteger).
The field could look like this:
<numberOfSandGrains
jcr:primaryType="cq:Widget"
fieldLabel="Number of grains of sand at the beach"
name="./grainsCount"
regex="/\d+/"
regexText="Please enter a numeric value."
xtype="textfield"/>
Solution 2 - change scale
Another option is to change the logic behind the configuration and use some different units if applicable. For instance, if the value 2222222222222222222222 is a number of grams (weight of an object/substance), it makes perfect sense to read it in metric tons instead (at least in many cases). The author could probably do without entering such humongous numbers.
You'll need to be extra-careful if you go this way.

Resources