Semantic-ui form rule only if option is selected - validation

I am using semantic ui and am trying to do some form validation with it.
The scenario I have is the user has 2 options: email,or phone app verrifcation. They select one of the options and enter whatever in a text field then click submit.
However I am not sure how to do rules on this with semantic UI.
I know if I wanted to check if it was blank I could do something like this:
$('.ui.form')
.form({
fields: {
CODE: {
identifier: 'code',
rules: [
{
type : 'empty',
prompt : 'Please enter your verification code'
}
]
}
} } );
However I would like additional rules based upon which option is selected. I have javascript that currently tells me the value of what is selected, and is updated on change. Unsure how to add it into the rules though, so that I can be like -- If phone was select, must be exactly 6 chars long, or IF email was selected, must be 18 chars long (different lengths for different option).
Is there a way to have conditional rules like this? Closet I could find was:
depends: 'id'
Which checks to ensure it is not empty.
Does anyone know how to have conditional rules such as this based on another form element? I am using the most recent version of Semantic-UI

You can do so by adding custom rules.
$.fn.form.settings.rules.atLeastOne = function (value, fields) {
fieldsToCompare = fields.split(",")
if (value) {
// current input is not empty
return true
} else {
// check the other input field(s)
// atLeastOne is not empty
atLeastOne = false
for (i = 0; i < fieldsToCompare.length; i++) {
// gets input based on id
if ($("#" + fieldsToCompare[i]).val()) {
atLeastOne = true
}
}
return atLeastOne
}
}
$(".ui.form").form({
fields: {
number:{
identifier: "number",
rules: [{
type: "exactLength[6]",
prompt: "number has to be 6 chars long"
}, {
// include the input fields to check atLeastOne[email, address, ...]
type: "atLeastOne[email]",
prompt: "Please provide an email or a number"
}]
},
email: {
identifier: "email",
rules: [{
type: "exactLength[18]",
prompt: "email has to be 18 chars long"
}, {
type: "atLeastOne[number]",
prompt: "Please provide an email or a number"
}]
}
}
});
Note that the function uses the input id as the identifier and not the input name. You might also want to look at optional fields.

Related

How can I specify a Yup error on a validating field's parent schema?

I'm trying to set up a validation schema to use with Formik. I have a combobox that has items of shape { id: number; value: string; } and pulls the value out to display to the user, while submitting the whole item to Formik/Yup. However, in production, I won't know the shape of my items ahead of time; this is just the shape I've chosen for demoing.
const items = [
{ id: 1, value: 'foo' },
{ id: 2, value: 'bar' },
];
const [ field, meta, helpers ] = useField('value');
return (
<ComboBox
{...field}
invalid={meta.touched && !!meta.errors}
invalidText={meta.errors}
items={items}
itemToString={i => i?.value ?? ''}
onChange={data => helpers.setValue(data.selectedItem)}
selectedItem={field.value}
/>
);
I want to make only id = 1 to be valid.
const validationSchema = Yup.object({
value: Yup.object({
id: Yup.number().oneOf([1], "You've selected an invalid option."),
value: Yup.string(),
})
.required('You have not selected an option.')
.nullable(),
});
However, when this is in the error state, meta.errors is set to { id: "You've selected an invalid option." }. invalidText expects a ReactChild so when it receives this object, React throws an error.
I assume the solution, then, is to move .oneOf() to outside of the inner Yup.object(). I don't know how to specify the valid values, however, and neither the documentation nor a quick search of SO helped. Thoughts?

Yup validation with one field but two possible options (OR)

I am trying to create an input that takes a string that will be used as the href value for a tag. The href can be a url OR an email (for mailto:).
It works if I just check for email, or if I just check for URL. However, I want to check for one or the other. I am looking through yup documentation but I can't find a way to do an OR.
I noticed that there is a when to test for another field but I'm not checking if another field is true or not, or use test but I also can't seem to get it to work.
const vSchema = yup.object().shape({
text: yup.string().required(),
href: yup
.string()
.email('Link must be a URL or email')
.url('Link must be a URL or email')
.required('Link is a required field'),
});
test this
yup.addMethod(yup.string, "or", function(schemas, msg) {
return this.test({
name: "or",
message: "Please enter valid url or email." || msg,
test: value => {
if (Array.isArray(schemas) && schemas.length > 1) {
const resee = schemas.map(schema => schema.isValidSync(value));
return resee.some(res => res);
} else {
throw new TypeError("Schemas is not correct array schema");
}
},
exclusive: false
});
});

Alter the text displayed for a token in ace-editor

I have this example where I am locating a matching string via regex and changing the styles using highlight rules.
this.$rules = {
start: [{
token: 'variableRef',
regex: /\$variable\..+\$/
}]
};
and alter the color using a css class:
.ace_variableRef {
color: red;
}
But what I would really like to do is change the text that is being displayed from $variable.1.name$ to the "resolved value". I have access to:
var variables = {
1: 'timeout'
};
so I can use the reference path to get the value, but is it even possible to do this with ace-editor?
Ideally I would display the string in the user friendly way, but keep the original reference value handy (in metadata or something) since that is what is actually stored in the db.
You can accomplish this by defining a custom onMatch for your rule, like so
this.$rules = {
start: [{
onMatch: function(value, state, stack) {
var values = this.splitRegex.exec(value);
return [{
type: 'variableRef',
value: variables[values[1]]
}]
},
regex: /\$variable\.(\d+).+\$/
}]
};
but the actual text will remain unaltered (thus causing oddities with text selection/cursor), so you'll need to pad/clip the resulting value for it to match length of values[0]

Assistance with a custom jquery validate error message function

We have a rule that all of our validation messages must be in a summary, and thus the default "this field is required" doesn't cut it because the messages lose their context in a summary and therefore need specific field indicators.
I have a solution that I like rather well, but it soon became clear that there was a need for messages outside of just the required field (email, url, custom methods like phoneUS, etc), so I made some additions to my function.
I've been using jQuery for a while, but I'm not an expert in the optimization area, so I wanted to get some expert help on whether the function below could be optimized...my question is, "is there actually a better way to handle custom error messages in a summary?"
$('.required, .email').each(function(index) {
var $this = $(this);
var label = (
$this.is(':radio')
? $("label[data-name='"+$this.attr('name')+"']")
: label = $("label[for='"+$this.attr('id')+"']")
);
var customMessages = [{}];
if($this.hasClass('required')){
customMessages.required = "'" + label.text() + "' is required.";
}
if($this.hasClass('email')){
customMessages.email = "'" + label.text() + "' has an invalid email address.";
}
$this.rules("add", {
messages: customMessages
});
});
Here is the jsFiddle:
http://jsfiddle.net/GD5nw/1/
So why not just assign the custom message on a field-by-field basis for each field as is most typically done? It seems less verbose than what you've been doing.
http://docs.jquery.com/Plugins/Validation/validate#toptions
Example for input elements with name attribute assigned as first, second, and address.
$('#myform').validate({
rules: {
first: {
required: true
},
second: {
required: true
},
address: {
required: true,
digits: true // just an example
}
},
messages: {
first: {
required: "your first name is required"
},
second: {
required: "your last name is required"
},
address: {
required: "your address is required",
digits: "must only use digits on address"
}
}
});
Working Demo: http://jsfiddle.net/x4YBw/

Credit card validation problem using multiple textbox

I'm using multiple textboxes for users to entry different credit cards#, with jquery validations. Ambiguously, only the first text box validation is working. Validation's are not working for the other boxes. There are no js errors too in error console.
It'll be very helpful if someone can please give me a clue.
//for first textbox
$("#cust_reg").validate({
rules: {
cc_num_local: {
required: true,
creditcard: true
}
}
});
//for second textbox
$("#cust_reg").validate({
rules: {
cc_num_roam: {
required: true,
creditcard: true
}
}
});
the relevant html only: http://pastie.textmate.org/2422338
You can have more then one HTML element using the id of cust_reg. If you do then only one will be available to your JavaScript code since one supersedes the other. It also isn't valid HTML. You'll need to change the name of the second field to be something different like cust_reg2.
Since you have one form and two different ID's you might try combining them in your code.
$("#cust_reg").validate({
rules: {
cc_num_local: {
required: true,
creditcard: true
},
cc_num_roam: {
required: true,
creditcard: true //Not sure if this can be the same name
}
}
});

Resources