Javascript

How do we make our apps interactive with modern JS implementation

Jquery

We want to remove all the legacy jquery.

VueJs (new way)

app/views/layouts/new_layout.html.slim
= javascript_pack_tag "application"
app/frontend/packs/vue-app.js
document.addEventListener('DOMContentLoaded', () => {
  new Vue({
    el: '[data-behavior="vue"]'
  })
})

This waits for the DOM-tree to load and then starts to initialize a vue-app. It works just as jQuery, ready(), but without jQuery.

Components

Example

app/frontend/components/header.vue
<template lang="pug">
  .bg-black.text-white.sticky.top-0.z-10.transition-all.duration-300.ease-out(
    class="xl:text-gray-900"
    :class="scrolled ? 'xl:bg-white xl:shadow' : 'xl:bg-transparent xl:shadow-none'"
  )
    .container.relative
      slot
</template>

<script>
export default {
  data () {
    return {
      scrolled: false
    }
  },
  created () {
    document.addEventListener('scroll', () => {
      this.scrolled = window.pageYOffset != 0
    })
  }
}
</script>
app/frontend/packs/vue-app.js
import Vue from 'vue/dist/vue.esm'
import Drawer from '../components/drawer'

Vue.component('app-drawer', Drawer)
app/views/front/products/houses/show/_how_to.html.slim
.container.my-40
  .grid.items-center class="lg:grid-cols-2"
    = image_pack_tag 'products/houses/how-it-works.jpg', class: 'hidden lg:block'
    div class="lg:ml-16 xl:ml-32"
      .text-blue-500.text-sm.uppercase = t('.pretitle')
      = component 'title', tag: 'h2', class: 'text-5xl mb-4', content: t('.title').html_safe
      .grid.gap-6.mt-12
        app-drawer
          template slot="title"
            = icon "money-wallet-1", class: 'text-gray-700 flex-shrink-0 mr-3'
            h3.text-2xl.text-gray-900.font-medium = t('.drawers._1.title')
          = icon 'arrow-down-1', slot: 'arrow'
          p == t('.drawers._1.content')

Linting

The vue plugin of eslint is set at the 'recommended' level to lint our code in .eslintrc.js.

yarn lint

Known issue

  • vue-cli-service: command not found

Solution

  • rm -rf node_modules yarn.lock && yarn install

i18n

Gemfile
gem 'i18n-js'
app/views/layouts/new_layout.html.slim
= javascript_tag do
  | I18n.locale = "#{I18n.locale}";
  | I18n.translations = #{raw I18n::JS.filtered_translations.to_json};
app/frontend/packs/vue-app.js
import I18n from 'i18n-js'

global.I18n = I18n
Vue.prototype.$t = I18n.t
Vue.config.productionTip = false

Usage

{{ $t('front.products.houses.show.hero.form.call_to_action') }}

Tip: When going from i18n stored in Rails to i18n handled directly in the front, ruby -rjson -ryaml -e "puts YAML.load_file('path/file_to_convert.yml').to_json" will take a .yml file and output its corresponding JSON for ease of conversion.

VueJs (old way)

Forms

Even if some forms still use some jquery, most of the SeraphinWeb forms are enhanced with a Vuejs app (#vueApp) to manipulate the DOM.

Profiling forms

The majority of our products purchase process begin with a profiling form to gather product oriented data and data from the user.

Two Vue apps are used :

  • #vueApp- for all the product specific questions

  • #vueProfiling - for the generic shared questions on the user

The profiling Vue app :

  • is in shared partial, so it needs to be included in the view

  • needs to get data from the back end form : data: #{ raw form.serialized_data.to_json }

Note that the back end profiling form needs to have the serialized_datamethod accordingly.

Mixins

It exists a special Vue instance with sole purpose to be used as a mixin by other Vue app. This Vue app is stateless and only contains helper methods.

Script

To enhance SeraphinWeb front end, some scripts are injected.

examples :

  • <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

  • <script src='https://maps.googleapis.com/maps/api/js?...'></script>

  • <script src='https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.7.0/intro.min.js'></script>

Polyfills

Because SeraphinWeb needs to be compliant with old browsers (IE, safari...), polyfills are used.

examples :

  • <script src='https://cdn.polyfill.io/v2/polyfill.min.js?features=default,Array.prototype.includes'></script>

  • <script src='https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.auto.min.js'></script>

Last updated