LahiruChathuranga
LahiruChathuranga

Reputation: 237

Uncaught TypeError in custom directive library

I have created a custom directory for tooltip and I want make it as a library that can be import and use in any other projects. I have create the library and import in different project. But when I run the project it returns below error.

Uncaught TypeError: Cannot read property 'install' of undefined
at Function.Vue.use (webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:5096)
at eval (webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/CommonComponents/WizardComponent.vue?vue&type=script&lang=js&:35)
at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/CommonComponents/WizardComponent.vue?vue&type=script&lang=js& (app.js:1022)
at __webpack_require__ (app.js:849)
at fn (app.js:151)
at eval (webpack-internal:///./src/components/CommonComponents/WizardComponent.vue?vue&type=script&lang=js&:2)
at Module../src/components/CommonComponents/WizardComponent.vue?vue&type=script&lang=js& (app.js:1838)
at __webpack_require__ (app.js:849)
at fn (app.js:151)
at eval (webpack-internal:///./src/components/CommonComponents/WizardComponent.vue:3)

I tries several ways to publish the custom directive library and could not be fixed yet. It is a great help if you can help me to find the issue.

My library code is below

main.js

export const tooltip= {
  bind: function (el, binding) {
    el.addEventListener('mouseenter', function () {
      var $tooltip = document.createElement('div')
      var $tooltipDimension = el.getBoundingClientRect()
      var $tooltipPopupDimension = $tooltip.getBoundingClientRect()
      $tooltip.setAttribute('class', 'v-tooltip')
      $tooltip.setAttribute('id', 'vTooltip')
      var tooltipObj=binding.value;
      var toolTipValue=null;
      var toolTipDirection=null;
      var toolTipBackgroundColor=null;
      var toolTipTextColor=null;
      var toolTipPadding=null;
      var toolTipBoxShadow=null;
      if(typeof tooltipObj === 'object' && tooltipObj !== null){
        toolTipValue=tooltipObj.value;
         toolTipDirection=tooltipObj.direction;
         toolTipBackgroundColor=tooltipObj.backgroundColor;
         toolTipTextColor=tooltipObj.textColor;
         toolTipPadding=tooltipObj.padding;
         toolTipBoxShadow=tooltipObj.boxShadow;
         
      }
      $tooltip.innerHTML = toolTipValue;
      if(toolTipBackgroundColor!=null){
        $tooltip.style.backgroundColor=toolTipBackgroundColor;
        $tooltip.style.borderColor=toolTipBackgroundColor;
      }
      if(toolTipTextColor!=null){
        $tooltip.style.color=toolTipTextColor;
      }
      if(toolTipPadding!=null){
        $tooltip.style.padding=toolTipPadding;
      }
      if(toolTipBoxShadow!=null){
        $tooltip.style.boxShadow=toolTipBoxShadow;
      }
      document.body.appendChild($tooltip)
      if(toolTipDirection!=null && toolTipDirection=='bottom'){
        $tooltip.classList.add('bottom');
        $tooltip.style.left = $tooltipDimension.left - $tooltip.clientWidth/2 + $tooltipDimension.width/2 + 'px'
        $tooltip.style.top = $tooltipDimension.bottom + 6 + 'px'
      }else if(toolTipDirection!=null && toolTipDirection=='left'){
        $tooltip.classList.add('left');
        $tooltip.style.left = $tooltipDimension.left - $tooltip.clientWidth - 6 + 'px'
        $tooltip.style.top = $tooltipDimension.top + 'px'
      }else if(toolTipDirection!=null && toolTipDirection=='right'){
        $tooltip.classList.add('right');
        $tooltip.style.left = $tooltipDimension.left +  $tooltipDimension.width + 6 + 'px'
        $tooltip.style.top = $tooltipDimension.top + 'px'
      }else{
        $tooltip.classList.add('top');
      $tooltip.style.left = $tooltipDimension.left - $tooltip.clientWidth/2 + $tooltipDimension.width/2 + 'px'
      $tooltip.style.top = $tooltipDimension.top - $tooltip.clientHeight + 'px'
    }
      
    
      fadeIn($tooltip)
    })
    el.addEventListener('mouseleave', function () {
      var elemToRemove = document.getElementById('vTooltip')
      fadeOut(elemToRemove)
      elemToRemove.parentNode.removeChild(elemToRemove)
    })
  }
}


function fadeOut(el){
  el.style.opacity = 1;

  (function fade() {
    if ((el.style.opacity -= .1) < 0) {
      el.style.display = "none";
    } else {
      requestAnimationFrame(fade);
    }
  })();
}

function fadeIn(el, display){
  el.style.opacity = 0;
  el.style.display = display || "block";

  (function fade() {
    var val = parseFloat(el.style.opacity);
    if (!((val += .1) > 1)) {
      el.style.opacity = val;
      requestAnimationFrame(fade);
    }
  })();
}

index.js

import './scss/tooltip.scss';
import tooltip from './main.js';

Vue.directive('tooltip', tooltip);

This is the packages json file where I wrote the code line to build the library

package.json

{
  "name": "v-lib-tooltip-component",
  "version": "0.0.6",
  "private": false,
  "main":"./dist/ToolTipComponent.common.js",
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "build-lib": "vue-cli-service build --target lib --name ToolTipComponent ./src/main.js",
    "npm-publish": "npm publish --access public",
    "yarn-publish": "yarn publish"
  },
  "files": [
    "dist/*",
    "src/*",
    "public/*",
    "*.json",
    "*.js"
  ],
  "dependencies": {
    "core-js": "^3.6.5",
    "css-loader": "^5.2.4",
    "node-sass": "^5.0.0",
    "sass-loader": "^10.1.1",
    "vue": "^2.6.11",
    "vue-router": "^3.5.1"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "vue-template-compiler": "^2.6.11"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

And when I use the above library in another project. This is the way I usedin vue file.

test.vue

import Vue from "vue";
import {VisitToolTip} from 'visit-lib-tooltip-component';
Vue.use(VisitToolTip);

Upvotes: 0

Views: 98

Answers (1)

tony19
tony19

Reputation: 138196

main.js has a named export tooltip that needs to be imported in index.js:

import { tooltip } from './main'

A Vue plugin must export an install function, so your index.js should be:

export default {
  install(Vue) {
    Vue.directive('tooltip', tooltip)
  }
}

Your build-lib command should target index.js, where the plugin code lives:

{
  "scripts": {
    "build-lib": "vue-cli-service build --target lib --name ToolTipComponent ./src/index.js",
  }
}

Finally, the tooltip plugin is not using named exports, so just use default imports when importing the plugin in your application:

// src/main.js (application project)
import VisitToolTip from 'visit-lib-tooltip-component';
Vue.use(VisitToolTip);

Upvotes: 1

Related Questions