4

I want to reuse a javascript library I did some time ago in a vue.js component.

The js library works like this:

  1. simple reference on the main script with tag
  2. css loading

The library provides a constructor, so what is needed is a element with an ID and to init the component in javascript I only need to:

var divelement = new pCalendar("#divelement", {
    ... various options
});

I'm trying to create a .vue component that is able to do the same (loading js library, init css, init component with the constructor and options), but I can't figure out what is the right way to do it.

This is what I'm working on, but in this situation I get an error because pCalendar is not recognized as constructor.

<template>
    <div id="myelement"></div>
</template>
<script>
    import perpetual_calendar from '../../../assets/js/perpetual-calendar/perpetual_calendar.js'
  export default {
    data () {
      return {
        myelement: '',
      }
    },
    mounted(){
          var myelement = new pCalendar("#myelement",{
        ... various options
});        
      } ,  

 }
</script>
<style lang="css">
    @import '../../../assets/js/perpetual-calendar/pcalendar_style.css';
</style>

Edit 1 (answer to @Daniyal Lukmanov question):

perpetual_calendar.js looks like this:

var pCalendar = function (element, options) {
    this.options = {};
    this.initializeElement(element);
    this.initializeOptions(options || {});
    this._create();
}
...

pCalendar.prototype.initializeElement = function (element) {
    var canCreate = false;
    if (typeof HTMLElement !== "undefined" && element instanceof HTMLElement) {
        this.element = element;
        canCreate = true;
    } else if (typeof element === "string") {
        this.element = document.querySelector(element);
        if (this.element) {
            canCreate = true;
        } else {
            canCreate = false;
        }
    } else {
        canCreate = false;
    }

    if (canCreate === true) {
        if (document.getElementsByName(this.element.id+"_store").length!=0) {
            canCreate = false;
        }    
    }
    return canCreate;
};

and so on ...

Edit 2: this is the initializeOptions function, that is throwing the TypeError: "this.element is null" error.

pCalendar.prototype.initializeOptions = function (options) {
    // begin hardcoded options, don't touch!!!
    this.options['objectId'] = this.element.id;
    this.options['firstMonth'] = null;
       (... various options)
    // end hardcoded options

    for (var key in this.defaultOptions) {
       ( ... loop to load options - default one or defined by user in the constructor)
    }
};
3
  • How does perpetual_calendar.js look like? And what is pCalendar if you import perpetual_calendar? Commented Jan 22, 2020 at 8:56
  • @DaniyalLukmanov, I've just edidted the question in order to give you more details. Commented Jan 22, 2020 at 9:20
  • 3
    If you don't export pCalendar you obviously won't be able to use it outside perpetual_calendar.js Commented Jan 22, 2020 at 9:25

1 Answer 1

2

In you perpetual_calendar.js file, you need to export the pCalendar in order to use it. At the bottom of the perpetual_calendar.js file, add:

export {
  pCalendar
};

Now, you should be able to import and use it like so:

import { pCalendar } from './perpetual_calendar.js';
let calendar = new pCalendar({ /* parameters*/ });

EDIT After adding initializeElement method

There are a few things wrong in the code:

  1. It seems that not all code paths of initializeElement set the this.element variable.
  2. document.querySelector will not work in vue. You will need to pass the element via the this.$refs variable:
<template>
    <div id="myelement" ref="myelement"></div>
</template>
<script>
    import perpetual_calendar from '../../../assets/js/perpetual-calendar/perpetual_calendar.js'
  export default {
    data () {
      return {
        myelement: '',
      }
    },
    mounted(){
          var myelement = new pCalendar(this.$refs["myelement"], { /* various options */ });        
    }

 }
</script>
<style lang="css">
    @import '../../../assets/js/perpetual-calendar/pcalendar_style.css';
</style>

Now, you can pass the element to your perpetual_calendar as directly as an object instead of having to use document.querySelector:

pCalendar.prototype.initializeElement = function (element) {
    this.element = element.
    return true;
};
Sign up to request clarification or add additional context in comments.

7 Comments

I've tried also this, but it is not working. I've added the pCalendar definition inside the library in the question.
Okay, I've updated my answer as I see what the issue is now.
Ok, it finally makes sense... But I'm getting a TypeError: "this.element is null" in console. In fact, element is null and is not linked anyhow on the <div> element that is delcared in <template>.
Can you update your post with the new code that is throwing this exception? Or maybe even create a new question so that the context of this one is not lost for other people having this issue.
Updated my answer. In short, it comes down to the document.querySelector not being available in vue. What you will have to do is add a ref attribute to you HTML element, and access it using the this.$refs variable.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.