Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I establish two cleave.js formatted fields in the same js file?

I want to format both phone and credit card input using cleave.js (in rails). I've got the formatting working if I only declare one new Cleave object, but I get this error if I attempt to declare two:

Uncaught Error: [cleave.js] Please check the element

Here's the relevant parts of the JS file:

var Global = {};

Global.onLoad = function(){
  Global.setupDatepickers(); //unrelated function
  Global.setupCleavePhone();
  Global.setupCleaveCreditCard();
};

$(document).on('turbolinks:load', function(){
  Global.onLoad();
});

Global.setupCleavePhone = function() {
  new Cleave('.phone-input', {
    phone: true,
    phoneRegionCode: 'US',
    delimiter: '-'
  });
}

Global.setupCleaveCreditCard = function() {
  new Cleave('.card-input', {
    delimiter: '-',
    blocks: [4,4,4,4]
  });
}

I've tried a few remixes of this including assigning the Cleave objects to variables and declaring them in the same function, but no dice. Here's a jsfiddle of multiple cleave objects being delared at once, and I can't see any meaningful differences between my code and theirs. The selector classes are properly applied in the view. Any thoughts why I can't seem to format two fields at once?

like image 758
Daniel Grimes Avatar asked Nov 16 '16 16:11

Daniel Grimes


2 Answers

SOLVED:

As it turned out it needs the objects to exist in order to run new Cleave. If one of the elements doesn't exist on the page, the whole thing fails for some reason. I ended up going with wrapping each new Cleave, checking if an element with that class existed or not, for example:

if ($('.card-input').length) {
  new Cleave('.card-input', {
    delimiter: '-',
    blocks: [4,4,4,4]
  });
}

UPDATE:

Or even better, if you're like me and need to format more than one object of the same class on a page (which causes cleave to only format the first one with the code above) retrieve the array of objects and run cleave on each. It performs the same 'does it exist' check as well as formatting each object. For example:

for(let field of $('.zip_code').toArray()){
  new Cleave(field, {
    numericOnly: true,
    delimiter: ' ',
    blocks: [5,4]
  });
}

UPDATE AGAIN:

So as it turns out the above is less than ideal because, as I understand it, the above let-of loop (like for-in loops) will iterate across the enumerable objects of an array, instead of just over its indices. Have a look at this answer if you too would like interpret what that's about: For-each over an array in JavaScript?.

As well, I couldn't precompile my assets for production becasue it hated the use of let, and while changing let-of to for-in also worked, I ended up going with the more specific forEach loop.

$('.zip-code').toArray().forEach(function(field){
   new Cleave(field, {
      numericOnly: true,
      delimiter: ' ',
      blocks: [5,4]
   })
});
like image 99
Daniel Grimes Avatar answered Nov 06 '22 07:11

Daniel Grimes


this should work as well

$('.zip-code').each(function (index, ele) {
    var cleaveCustom = new Cleave(ele, {
        numericOnly: true,
        delimiter: ' ',
        blocks: [5, 4]
    });
});
like image 1
irfandar Avatar answered Nov 06 '22 08:11

irfandar