Sometime the user need to fill multiple fields in form, also each of them must be unique. Any of them has to be different to the remaining.
You might think of using the
different validator which requires two fields to be different to each other,
such as an username and password shouldn't be the same. In our case, the different validator isn't useful because the number of fields
for doing comparison are unknown.
The form in this example asks user to provide some email addresses. User is also required to fill at least one email address.
Each of them, if present, must be unique. This kind of form can be seen in a lot of forms nowadays.
The approach illustrated in this example is that:
- Use the emailAddress validator to ensure each field need to be a valid email address
- Use the callback validator validator to check if the list of email addresses consist duplicated item
- If all fields pass these validators, we then use the
updateFieldStatus()
method to set them as valid fields
That are straight forward steps. The next sections show the implementation in details.
Checking duplicate items in array
In order to check whether an array contains duplicated items or not, we can use a simple implementation:
const hasDuplicatedItems = function (inputArray) {
const obj = {};
const numItems = inputArray.length;
const duplicateRemoved = [];
for (const i in inputArray) {
obj[inputArray[i]] = 0;
}
for (const i in obj) {
duplicateRemoved.push(obj[i]);
}
return duplicateRemoved.length === numItems;
};
Since the array of email addresses might consist of empty item, we need to adjust the code above a little bit to ensure that the array has at least one not-empty item and doesn't contain any duplicated items:
let notEmptyCount = 0;
const obj = {};
const duplicateRemoved = [];
for (const i in emailElements) {
const v = emailElements[i].value;
if (v !== '') {
obj[v] = 0;
notEmptyCount++;
}
}
for (const i in obj) {
duplicateRemoved.push(obj[i]);
}
if (duplicateRemoved.length === 0) {
} else if (duplicateRemoved.length !== notEmptyCount) {
}
Using the same names
The example code below demonstrates the implementation when all email fields use the same names, email[]
, for example.
const form = document.getElementById('demoForm');
const fv = FormValidation.formValidation(
document.getElementById('demoForm'),
{
fields: {
'email[]': {
validators: {
emailAddress: {
message: 'The value is not a valid email address'
},
callback: {
callback: function(input) {
...
if (duplicateRemoved.length === 0) {
return {
valid: false,
message: 'You must fill at least one email address',
};
} else if (duplicateRemoved.length !== notEmptyCount) {
return {
valid: false,
message: 'The email address must be unique',
};
}
fv.updateFieldStatus('email[]', 'Valid', 'callback');
return {
valid: true,
};
}
},
}
}
},
plugins: {
...
},
}
);
Using different names
What if the email fields have different names? How we can set the validator rules for them?
In this case, we can use a same CSS class for all email fields:
<input type="text" class="js-user-email" name="user.email[0]" />
<input type="text" class="js-user-email" name="user.email[1]" />
<input type="text" class="js-user-email" name="user.email[2]" />
<input type="text" class="js-user-email" name="user.email[3]" />
and then use the
selector option to apply the same set of validation rules for them:
const form = document.getElementById('demoForm');
const fv = FormValidation.formValidation(
document.getElementById('demoForm'),
{
fields: {
'email[]': {
selector: '.js-user-email',
validators: {
...
}
}
},
plugins: {
...
},
}
);
See also