JasonMHirst
JasonMHirst

Reputation: 576

Importing a common library into a Vue SPA

Having a hard time trying to understand what I imagine should be a simple task, but am prepared to accept that maybe I'm approaching this the wrong way and willing to change my plan into the proper way.

In short I have a .js file which contains hundreds of objects and functions that are used in our applications. We're modernising our approach and refactoring some of the functions.

As a very basic example I have:

**COMMON.JS**
const dynamicYearColumn= {
    resizable: false, suppressMovable: true, sortable: true, width: 100, menuTabs: [], type: 'numericColumn',
}


const defaultPercentageColumn= {

    resizable: false, suppressMovable: true, sortable: true, width: 150, menuTabs: [], type: 'numericColumn',
    //comparator: customPercentageCompare,
    valueFormatter: formatPercent,
    cellStyle: { 'text-align': 'right' },
    cellClass: function (params) { var className = numberToColorClass(params.value); return className }
}


function formatPercent(number) {

    if (isNaN(number.value) == true) { return '-' }
    return isFinite(numberWithCommas(parseFloat(number.value, 2).toFixed(this.defaultDecimalRounding))) ? numberWithCommas(parseFloat(number.value, 2).toFixed(this.defaultDecimalRounding)) + '%' : '?';
}

function numberWithCommas(n) {
    var parts = n.toString().split("."); return parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (parts[1] ? "." + parts[1] : "");
}

Within my main.js, I now have:

import common from './scripts/common.js'
const commonLibrary = {
    install() {
        Vue.common = common
        Vue.prototype.$common = common
    }
}

Vue.use(commonLibrary)

And this is where I'm failing to succeed.

In my common.js, if I enclose the code within export default I have to change the code (removing the const's so the objects are actual object definitions, and formatPercent is then unrecognised.

If I export {dynamicYearColumn,defaultPercentageColumn} then that 'kinda' works, but I still get undefined on formatPercent and numberWithCommas.

Likewise if I try the create a Mixin, then this too works, but any functions within the Mixins methods are unrecognised PLUS I've been advised not to push such a large library into Mixins as this isn't very good practice.

I appreciate there's an abundance of sources out there with good examples, but to be honest I can't really think of the correct terminology to even start looking for working examples.

TLDR;

I simply want to allow access to a large collection of objects and functions from a single JS file and called from my Vue SPA on any component.

Upvotes: 0

Views: 79

Answers (1)

skirtle
skirtle

Reputation: 29092

It sounds like you're almost there.

Let's assume that you want to do this:

import common from './scripts/common.js'

To achieve this we need common.js to have a default export. So something starting export default.

Further, let's assume we want to access the objects and functions as common.dynamicYearColumn, common.formatPercent, etc.. Even ignoring the import/export part this implies that common needs to be an object with properties called dynamicYearColumn, formatPercent, etc.. Some of those properties will be functions but that doesn't really make much difference.

So let's briefly consider how we could build such an object.

const common = {}
common.dynamicYearColumn = { /* object properties here */ }
common.formatPercent = function (number) { /* implementation here */ }

Of course object literals allow us to define the object with these properties straightaway, rather than adding them later:

const common = {
  dynamicYearColumn: { /* object properties here */ },
  formatPercent: function (number) { /* implementation here */ }
}

ES6 added some syntactic sugar to simplify the creation of functions within an object, so this can be reduced down to:

const common = {
  dynamicYearColumn: { /* object properties here */ },
  formatPercent (number) { /* implementation here */ }
}

This is the object that we want to create within common.js and then export. Putting it all together we get:

export default {
  dynamicYearColumn: {
    // ...  
  },

  defaultPercentageColumn: {
    // ...
  },

  formatPercent (number) {
    // ...
  },

  numberWithCommas (n) {
    // ...
  }
}

Adding them to the Vue.prototype, as you are in your example, will make them available within your component as:

this.$common.formatPercent(25)

In your templates it would be:

{{ $common.formatPercent(25) }}

This is all good but note that you won't be able to use the functions as filters. So you can't write this:

{{ 25 | $common.formatPercent }}

If that's something you want then you'll have to register those functions as filters within your plugin.

Upvotes: 1

Related Questions