95% of my fields for a form I have use a custom validator -> hence I include it as apart of my defaults config of the container.
However, for the remaining 5% of fields, I want to use the built-in validation. Is there a way to manually specify using the default validator for a given field type?
Currently I try,
{
name: 'normalNumberField',
xtype: 'numberfield',
validator: Ext.form.field.Number.validate,
...
}
but I'm getting an error that Ext.form is undefined (why? I clearly have a reference to Ext ... )
The validator is not specified by default. Number field validation occurs in multiple steps (this is taken from the ExtJS docs):
Field specific validator
A validator offers a way to customize and reuse a validation specification. If a field is configured with a validator function,
it will be passed the current field value. The validator function
is expected to return either:
Boolean true if the value is valid (validation continues).
a String to represent the invalid message if invalid (validation halts).
Basic Validation
If the validator has not halted validation, basic validation proceeds as follows:
allowBlank : (Invalid message = blankText)
Depending on the configuration of allowBlank, a
blank field will cause validation to halt at this step and return
Boolean true or false accordingly.
minLength : (Invalid message = minLengthText)
If the passed value does not satisfy the minLength
specified, validation halts.
maxLength : (Invalid message = maxLengthText)
If the passed value does not satisfy the maxLength
specified, validation halts.
Preconfigured Validation Types (VTypes)
If none of the prior validation steps halts validation, a field
configured with a vtype will utilize the corresponding
Ext.form.field.VTypes validation function. If invalid, either the
field's vtypeText or the VTypes vtype Text property will be used
for the invalid message. Keystrokes on the field will be filtered
according to the VTypes vtype Mask property.
Field specific regex test
If none of the prior validation steps halts validation, a field's configured regex test will be processed. The
invalid message for this test is configured with regexText
Number field specific validation
The additional validations run test that the value is a number, and
that it is within the configured min and max values.
So, long story short, to override your validator that you specified in defaults, you can simply use a validator which always returns true.
{
name: 'normalNumberField',
xtype: 'numberfield',
validator: function(){ return true; },
...
}
Related
I am working on converting forms from Formik over to React Hook Form. yup is the validator in both cases. However I've noticed that despite leaving the validation schema in tact, there seems to be some sort of hierarchy mismatch between Formik and RHF.
I noticed for instance that for min, max, required, originally in that order, validation was working correctly with Formik, but I had to invoke required before min & max in order for the correct validation message to trigger on an input. That fix was self-explanatory enough.
But some of these are tricky. For instance:
dob: yup.date().when([], (schema: yup.DateSchema) => {
return boolCheck1 && boolCheck2
? yup.string()
: schema
.min(
moment.utc().add(1, 'day').subtract(126, 'years').toDate(),
'an error message'
)
.max(
moment.utc().subtract(15, 'years').toDate(),
'another error message'
)
.transform((_, originalValue) => {
const date = moment.utc(originalValue, 'MM/DD/YYYY');
return date.isValid()
? date.startOf('day').toDate()
: new Date('');
})
.typeError('A valid date is required (MM/DD/YYYY)')
.required('Please enter a valid date');
})
It seems that regardless of where I am placing the required check, the one that is triggered is typeError ("A valid date is required (MM/DD/YYYY)"). Basically, if a user touches and blurs this input field without having typed anything, it should trigger the required message ("Please enter a valid date".) Only when a user types something that does not pass the typeError check should the typeError message appear.
This was working previously with Formik. However, now, I'm using React Hook Form as such:
const rhfMethods = useForm({
defaultValues,
resolver: yupResolver(validationSchema),
mode: 'onTouched',
});
The only difference really is that now the yupResolver is being used (without which I get a typescript error.)
If anyone could shed any light on this that would be greatly appreciated!
Nvm, looks like a similar question had already been asked and answered.
While that definitely helped shed light on the issue ('' is still a string type, not simply no data), what helped me solve this was this addendum.
I still needed the initial '' to be a valid input type, so instead of returning an Invalid Date (new Date('')) in the else case, I just needed to return undefined.
Final fix:
dob: yup.date().when([], (schema: yup.DateSchema) => {
return boolCheck1 && boolCheck2
? yup.string()
: schema
.min(
moment.utc().add(1, 'day').subtract(126, 'years').toDate(),
'an error message'
)
.max(
moment.utc().subtract(15, 'years').toDate(),
'another error message'
)
.transform((_, originalValue) => {
const date: moment.Moment = moment.utc(
originalValue,
'MM/DD/YYYY'
);
return date.isValid() ? date.startOf('day').toDate() : undefined;
})
.typeError('A valid date is required (MM/DD/YYYY)')
.required('Please enter a valid date');
})
(To be fair... I tried testing on the UI and there was no instance where this .typeError was ever triggered (even with Formik) since every allowable input instance (only numbers can be typed and they're auto-formatted to dates) was already being checked by the other tests... I think I could safely remove that typeError check altogether lol.)
I am creating a salesforce validation rule for one of the object which is related to Date field.
OR((Delivery_Date_From__c < TODAY()+1), (Placement_Date_From__c < TODAY()+1), true, false)
This gives me a validation, but when i remove the true, false from the validation formula, it doesn't give me any validation.
Thanks in advance.
By adding true to the OR function you are forcing it to always return true. Validation Rules cause an error when they return true, thus users will never be able to save a record. Instead try this:
OR(
AND(ISCHANGED(Delivery_Date_From__c), Delivery_Date_From__c <= TODAY()),
AND(ISCHANGED(Placement_Date_From__c), Placement_Date_From__c <= TODAY())
)
This way the comparison only happens if the date is actually being edited, and if the date is before or equal to today it will return true, causing validation to throw an error.
I am generating an HTML form from JSON using some custom directives. Part of the JSON include restrictions on the values of the fields.
One of the restrictions the JSON puts on fields is a positive decimal type. The code I use in my link function to accomplish this:
//...snip
if (<this field should be number>) {
elem.attr("type", "number");
}
This successfully changes the field type to number. However, there are two problems:
It does not allow negative numbers
Every time I type a key stroke (even for valid numbers), it throws a number format exception. For example, if I type "123" I will get the following 3 errors:
Error: [ngModel:numfmt] 1 to be a number
Error: [ngModel:numfmt] Expected 12 to be a number
Error: [ngModel:numfmt] Expected 123 to be a number
I know that the model is successfully changed to a number type because when I print it out with a directive it displays without quotes.
So my question is:
How do I allow negative numbers
How do I stop all of the exceptions from being
How to Dynamically Change the Type of an Input Element
The type of an input element can be changed dynamically simply with AngularJS interpolation.
<input type="{{dynamicType}}" ng-model="inputValue">
Or from a directive
angular.module("myApp").directive("typeVar", function() {
return {
link: linkFn
};
function linkFn(scope,elem,attrs) {
//elem.attr("type", "number");
attrs.$observe("typeVar", function(value) {
elem.attr("type", value);
//attrs.$set("type", value);
});
}
});
HTML
<input type-var="{{dynamicType}}" ng-model="inputValue">
The DEMO on JSFiddle
The type property is an intrinsic part of the input element. For more information, see MDN HTML Element Reference -- input.
I'm trying to create my own validation for password confirm, and putting my error on $error. this is my code:
html:
<input ng-model="user.password2" type="password" name="password2" required
ng-keyup="confirmPassword(user.password, user.password2)">
<div ng-messages="register.password2.$error" ng-if="register.password2.$dirty">
<div ng-message="required">Password is required</div>
<div ng-message="passwordsDontMatch">Passwords don't match</div>
</div>
JS:
$scope.confirmPassword = function (pass1, pass2) {
if (angular.isUndefined(pass1) || angular.isUndefined(pass2) || pass1.trim() != pass2.trim()) {
$scope.register.password2.$error["passwordsDontMatch"] = true;
} else {
delete $scope.register.password2.$error["passwordsDontMatch"];
}
console.log($scope.register.password2.$error);
};
it looks like it's working. when the passwords are the same, the message is not displayed and indeed the $error object is empty. But the input is still invalid: ($scope.register.password2.$invalid == true)
you can see what I'm talking about in this plunkr: http://plnkr.co/edit/ETuVqsdSaEBWARvlt4RR?p=preview
try 2 identical passwords. the message will disappear but when you blur from the input, it's still red because internally it's $invalid
The problem probably comes from the fact that you're not typing a password in the first field that matches your regex pattern. The first password is thus undefined, since it doesn't respect the ng-pattern validation rule.
That said, you shouldn't modify the $error array directly. Instead, you should set the validity of the field using $setValidity(). That will not only set and remove the error automatically, but also deal with the $invalid/$valid properties, add and remove the CSS classes, etc.
var valid = !((angular.isUndefined(pass1) || angular.isUndefined(pass2) || pass1.trim() != pass2.trim()));
$scope.register.password2.$setValidity("passwordsDontMatch", valid);
Here's a working example. But remember to enter a valid password in the first place.
Also, instead of implementing this check with ng-keyup, you should make it a directive, which would add a validator to the validators of the form input. This would make sure the check is made whatever the way the second password is entered (i.e. via copy/paste using the mouse only, or simply by prepopulating the form programmatically.
Angularjs has great infrastructure for form validation and showing error messages. But, I am in a situation that I have to show a warning message to a user in a specific scenario. Here is the diagram of my simple form
The form has required and pattern validation applied on both fields. In addition to this validation I want a warning message to be displayed to the user if VatAmount is not 20 percent of the InvoiceAmount. The warning will differ from validation in following aspects
It will not prevent the form submission
It will only appear if both fields (InvoiceAmount and VATAmount) are
valid
The warning should have a button or link that would read "Change and
proceed". When user presses that button the warning message will
hide and focus will be set to VATAmount field.
I believe this is a prefect use case for creating a directive. Actually, I have given it a try and put my effort in the form of a plunker. But my directive does not handle following cases
It appears even if the fields involved in warning are invalid
The show and hide functionality is not implemented (have no idea how
to target it)
Here is the link to the plunker
Your plunkr demo was on the right track; really you just needed to check for the special cases of when one of the values was empty.
I'd suggest calculating the fraction and storing it in the scope, and then watching that to see whether you should display your tax rate warning. Here's how to calculate the fraction. If either invoice.Amount or invoice.VAT is empty, the fraction will be set to null.
if (amt == null || vat == null) {
$scope.warning.fraction = null;
return;
}
$scope.warning.fraction = vat / amt;
This works because those properties will be set to undefined if the user doesn't enter a valid number due to your use of ng-pattern.
However, while it's nice to encapsulate this in a directive, you don't need to compile the template yourself. Just use the built-in ng-transclude directive. Then you can include a button that references the current scope like this:
<vat-warning>
Vat Amount is not 20%.
<button ng-click="invoice.VAT = invoice.Amount / 5">change</button>
</vat-warning>
Your directive would contain this declaration:
transclude: true,
template: '<span class="alert-warning" ng-show="warning.show" ng-transclude></span>'
Plus a controller to update the directive's local scope to manipulate the warning object. Here's an updated demo.
You need to calculate visibility of vat-warning tag in controller on basis of $error.required and $error.pattern of invoiceAmount and vatAmount and then use it as below:
$scope.isInvoiceAmountInvalid = function () {
var error = $scope.invoiceForm.invoiceAmount.$error;
var required = error.hasOwnProperty("required") && error.required;
var pattern = error.hasOwnProperty("pattern") && error.pattern;
console.log("Inside isInvoiceAmountInvalid", error, required, pattern);
return (required || pattern);
};
$scope.isVatAmountInvalid = function () {
var error = $scope.invoiceForm.vatAmount.$error;
var required = error.hasOwnProperty("required") && error.required;
var pattern = error.hasOwnProperty("pattern") && error.pattern;
console.log("Inside isVatAmountInvalid", error, required, pattern);
return (required || pattern);
};
Here is an updated plunker for the same