This is what I did to solve the problem. Kind of silly because it’s at a very basic level, but it works.
Since focusClassRemoved works at a field level, we need to validate each field in the card form. We start by declaring an object with all the fields initialized as false.
const cardFields = {
cardNumber: false,
expirationDate: false,
cvv: false,
postalCode: false
};
In the next line we set the card event listener:
card.addEventListener('focusClassRemoved', (e) => {
});
We then get the field and value contained in the callback:
let field = e.detail.field;
let value = e.detail.currentState.isCompletelyValid;
Since we don’t know the field that is being validated, we set it’s value in the object using the bracket notation.
cardFields[field] = value;
Then, we make sure that all the fields in the object are set to true.
if (Object.values(cardFields).every(item => item === true)) {
console.log('success');
} else {
console.log('fail');
}
Inside the if-else is were we are going to code our local variable of control. I’m using Validate.js, so I’m using a checkbox.
If all fields are true:
document.getElementById('token').value = 1;
document.getElementById('token').checked = true;
If at least one field is false:
document.getElementById('token').value = 0;
document.getElementById('token').checked = false;
The whole thing looks like this:
const cardFields = {
cardNumber: false,
expirationDate: false,
cvv: false,
postalCode: false
};
card.addEventListener('focusClassRemoved', (e) => {
let field = e.detail.field;
let value = e.detail.currentState.isCompletelyValid;
cardFields[field] = value;
if (Object.values(cardFields).every(item => item === true)) {
console.log('success');
document.getElementById('token').value = 1;
document.getElementById('token').checked = true;
} else {
console.log('fail');
document.getElementById('token').value = 0;
document.getElementById('token').checked = false;
}
});
The checkbox under the card form:
<input type="checkbox" id="token" name="token" style="visibility: hidden; position: absolute">
The form passes when the checkbox is checked.
I guess that’s more or less how Square would do a validate-all-fields solution. There has to be a better way to create the cardFields object based on the content of the form, in case Square decides to add the field “name on card” but I’ll leave it there.
Hope it helps.
Thanks, @seanmart, for the idea.