How and why we switched to Vue.js
Since long time we made in AppSoft a form of payment that you can see in the profile of any user of application. There is a slider, which allows to select the number of weeks. Depending on the slider, buttons are dynamically updating.
So, over the years the front-end code of this form has turned into the most terrible thing that a person can do with jQuery.
Let’s look at a few examples of this horror.
A huge number of conditional operators
1 2 3 4 5 6 7 |
if (window.location.pathname == "/dashboard/account") { $("#button-payment-block, .link-cancel").hide(); } else { $("#payment-block, #mentor-payment__login-form-container").hide(); var value = $("#button-payment-block").text().split(" ").splice(0,3).join(" "); $("#button-payment-block").html(value); } |
Enchanting string parsing
1 2 3 4 5 6 |
if ( $('.payment-form__weekly-price').html() ) { var arr = $(".payment-form__weekly-price").html().split(" "); var current_price_for_week = (options.total / (number_of_days / 7)).toFixed(1); arr.splice(3, 1, '€' + current_price_for_week); $('.payment-form__weekly-price').html(arr.join(" ")); } |
Constant DOM manipulations
1 2 3 4 5 |
$cardForm.show(); $cardForm.find('input[type=submit]').prop("disabled", false); $('.upgrade-block .upgrade__payment-block, .upgrade-block .upgrade__title, .upgrade-block .upgrade__info').hide(); $('#upgrade__payment-block--payment-button').hide(); $('.upgrade-block').css({'border': 'none'}); |
And in this way are made almost 284 lines of an unbearable hash that no one can figure out at all. The most complicated was, by the fact, that the id of the elements did not correspond to the meaning of it: #upgrade__payment-block–payment-button could turn out to be either a button for upgrading a subscription or a simple button for payment.
Hopefully, at this point, our dear reader already understood the size of tragedy.
Which JavaScript framework to choose
We considered two options for solving this problem:
- Rewrite all the code from 0 using the same technologies, but now to do it properly.
- Choose a library that “out of the box“ will make us write good code.
We were afraid that if we will choose the first option, again after a year we will not understand our own code. Therefore, we have chosen the second one. We needed a library or framework that:
- Allows you to introduce itself iteratively, only for small parts of the frontend;
- It will be powerful enough “out of the box“ to solve all our problems without unnecessary things;
- At the same time it will be simple to learn it at the right level for a couple of hours during a day off.
We didn’t choose long and carefully. Honestly, the choice was made immediately. After looking through the Vue.js documentation, we decided that we should try.
Webpacker, postcss, babel, yarn – go away
We launched a rail generator for front-end parts, hoping to quickly do the same with a webpack. Unfortunately, the generator added for us on top babel and postcss, which we didn’t plan to use. By the way, it turned out that we will still need to use yarn. At this point, our patience ran out and we removed all the rails generated rubbish.
The standard assets pipeline and connecting of third-party js libraries through gems or by dropping their vendor / assets work pretty fine in our case. Implementation immediately of big amount of new technologies, just because it is fashionable and cool, we don’t like.
We took vuejs-rails and picked up a couple more libraries (for the slider, for example) directly in vendor / assets. This approach, of course, has disadvantages but they are completely irrelevant at this stage.
Falling In Love With Vue.js
We will not teach you how to use Vue.js – it has the most excellent documentation. But if you want to truly become a master of this technology (especially in combination with Ruby on Rails), then read our experience and some impressions of implementing Vue.js in AppSoft.
Start with Vue.js
After spending about 6-7 hours with Vue.js, we managed to completely rewrite the entire front-end part of the payment form on Vue.js – and even roll it out into production. Not a bad result for a completely new technology for us.
The code on Vue.js is many times clearer and understandable.
If we count the number of code lines in our form, then payments.js decreased to 166 lines. Of these, 30+ goes to the appearance of the component for the slider – the component is good, but for some reason it forces us to describe its appearance directly in js code.
The Vue.js component itself only defines its properties and methods. Without going into details, here is what the new payment form code looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
Vue.component('payment-form', { template: '#payment-form-template', props: [ 'initial_upgrade', 'mentor_id', 'initial_number_of_weeks', 'current_user_is_present', 'has_mentor' ], data: function() { return { coupon: "", error_message: "", final_form_visible: this.mentor_id == null, // Either login or card details form loading: false, number_of_weeks: this.initial_number_of_weeks, price: 0, upgrade: this.initial_upgrade, upgrade_notice_visible: this.initial_upgrade, weekly_price: 0, card: { // ... }, slider: { // ... } } }, components: { 'vueSlider': window['vue-slider-component'], 'vueMaskedInput': window['VueTheMask'] }, computed: { can_proceed_to_final_form: function() { return !(this.number_of_weeks == 0 || (this.has_mentor && this.mentor_id != null)); } }, watch: { number_of_weeks: function(val) { this.setPrice(); }, coupon: function(val) { this.setPrice(); }, price: function(val) { this.weekly_price = (this.price / this.number_of_weeks).toFixed(1); } }, methods: { setPrice: function() { // ... }, getStripeToken: function(event) { // ... }, showFinalForm: function(event) { // ... }, toggleViews: function(event) { // ... } }, created: function () { this.setPrice(); } }) |
In the template, we indicate where to display these properties and with which action to use which method, for example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<a href="#" class="payment__button button button--centered" v-bind:class="[can_proceed_to_final_form ? '' : 'button--disabled']" v-if="!final_form_visible" v-on:click.prevent="showFinalForm"> <%= t ".enroll_for", price: "{{price}}" %> </a> <! --- > <template v-if="final_form_visible"> <p class="payment__notice payment__notice--centered"> <%= raw t '.to_continue' %> </p> <%= render "login_form" %> <%= link_to t('.cancel'), "#", class: "payment__cancel-link", "v-if" => "final_form_visible", "v-on:click.prevent" => "final_form_visible = false" %> </template> |
Elements themselves are hidden and displayed depending on the values of the component properties, and the binding of events to the elements (clicking on the button) is directly in the template.
It’s not very convenient to specify components without webpacker – but also not so difficult.
Ideally, the components in Vue.js are stored in separate file with the extension. vue. This file contains both: template and code, and even CSS. Refusing to use webpacker, we (probably) lost the ability to do this. Fortunately, Vue.js provides several alternative ways of defining components. The X-Templates method was perfectly for our system with assets pipeline:
1 2 3 4 5 |
<script type="text/x-template" id="payment-form-template"> <div class="payment" v-bind:class="[upgrade_notice_visible ? 'payment--large' : '']"> <! -- > </script> |
Vue.js is very convenient to be embed by parts
We have already partially talked about this, but it is worth noting once again: Vue.js does not force anyone to completely rewrite all the code. We took one specific component of the project – the payment form – and applied Vue.js. The rest of the front-end has not changed.
There are a million plugins for Vue.js
We were afraid that for Vue.js there would not be as many ready-made solutions as for jQuery. And it was not right. We immediately found ready-made components for the slider, for masked input. As well, we found components for datepicker, for tables and for anything else.
So, we managed to quickly convert the most complicated front-end component of the project to Vue.js. As a result, the code has become simpler, clearer, more maintainable. Vue.js is a great, simple, fast tool that doesn’t force you to learn new architecture. The impressions – you just write the code following a set of simple rules, and it works out well.
If you would like to create your own project with Vue.js or order any kind of custom software development – contact us right now!
Related Posts
Leave a Reply Cancel reply
Service
Categories
- DEVELOPMENT (102)
- DEVOPS (53)
- FRAMEWORKS (25)
- IT (24)
- QA (14)
- SECURITY (13)
- SOFTWARE (13)
- UI/UX (6)
- Uncategorized (8)