DEV Community

Cover image for Currency Input Masking with Cleave.js and Money gem in Ruby On Rails
Bilal Budhani πŸ‘¨β€πŸ’»
Bilal Budhani πŸ‘¨β€πŸ’»

Posted on

Currency Input Masking with Cleave.js and Money gem in Ruby On Rails

Relying on the user's input is a crucial part of building a robust application. That's why I try to apply strong validations on the incoming data on forms or otherwise. One of the important input which needs to be captured very precisely is –– Amount. Thou Rails ecosystem has an amazing gem called Money to work with the amount. However, I wanted an equally elegant experience while dealing with amount related inputs for my users on the front-end.

After playing around with a couple of Javascript libraries –– I ended up picking Cleave.js. I configured it to work in conjunction with Money gem. Here is the end result

Here's how to achieve this experience

First, let's get our dependencies added in our project

gem 'money-rails'
Enter fullscreen mode Exit fullscreen mode
yarn add cleave.js

rails g money_rails:initializer
Enter fullscreen mode Exit fullscreen mode

Then once we configure config/initializers/money.rb based on our requirements, we will move to set up the Javascript part.

In our app/views/layouts/application.html.slim we will define a global object in respect to Cleave.js configuration in the head tag. It should look something like this

/ Global config for input masking in Cleave library
javascript:
    window.__AMOUNT_INPUT_MASK__ = {
    prefix: "#{raw Money.default_currency.symbol} ",
    numeral: true,
    numeralThousandsGroupStyle: 'lakh',
    rawValueTrimPrefix: true
};
Enter fullscreen mode Exit fullscreen mode

tweak numeralThousandsGroupStyle config based on your requirement

In our app/assets/javascripts/application.js we will write a small piece of JS snippet which will attach input masking as per our defined Money config to any input which has a class currency-input-mask

document.addEventListener("DOMContentLoaded", function(event) {
    // Input Mask
    document.querySelectorAll("input.currency-input-mask").forEach(function(el) {
        new Cleave(el, window.__AMOUNT_INPUT_MASK__);
    });
});
Enter fullscreen mode Exit fullscreen mode

Now, any input field with above mentioned class will allow our users to enter values in a much more controlled fashion –– reducing the chance of human errors with more refined data.

There is just one last step which needs to be taken care before we move on. Because our input value now holds other data like currency & commas, which is what we are going to receive in parameters in our controller when the user submits the form.

To address this part, we will need to clean up the value before we can pass it on to our Model. Let's create a helper file in app/helpers called input_helper.rb and define a method to shave off wanted characters from the value

module InputHelper 
    def strip_inputmask(amount)
      amount.is_a?(String) ? amount.gsub(/#{Money.default_currency.symbol}|,/, '').strip.to_i : amount
    end
end
Enter fullscreen mode Exit fullscreen mode

Lastly, In our controller, we will include this helper and use the method we just defined

class ApplicationController 
 include InputHelper


 ...
 model.amount = strip_amount(params[:model][:amount])
 ...
end
Enter fullscreen mode Exit fullscreen mode

I believe this little care to our application has a drastic impact overall to the entire project and brings peace amongst all the stakeholders.

πŸ‘‹ Do let me know your thoughts or feedback if this was valuable in any way

originally posted on https://bilalbudhani.com/currency-input-masking-with-cleave-js-and-money-gem-in-ruby-on-rails/

Discussion (3)

Collapse
nickjj profile image
Nick Janetakis • Edited on

Cleave.js is really really good.

I just started using it over the weekend. Not only does it work for currency formatting but it excels at formatting credit card information too (card number, exp date and security code), and even has callbacks for giving you back the card type based on the first few digits of the card. Perfect for ferrying over that data to Stripe or another gateway.

Collapse
ben profile image
Ben Halpern

Neat!

Collapse
enzom97 profile image
enzoM97

Hi! How can I create the global js object in an application.html.erb file? I can't figure it out